اذهب إلى المحتوى

السؤال

نشر

كيف يمكنني إنشاء دالة تكرارية (أو كائن مكرر) في لغة بايثون؟ بحيث يمكن إستخدامه في حلقات التكرار مثل حلقة for ، على سبيل المثال عمل صنف Counter يمكن إستخدامه بالشكل التالي:

for i in Counter(3, 9):
    print(i)

 

Recommended Posts

  • 0
نشر

أولاً ماهو ال iterator: المكرر هو كائن يحتوي على عدد قابل للعد من القيم. وهو كائن يمكن التكرار عليه، مما يعني أنه يمكنك المرور على جميع القيم فيه. وبشكل عميق أكثر في Python ، المكرر هو كائن يقوم بتنفيذ بروتوكول المكرر، والذي يتكون من الطريقتين __iter __ () و __next __ ().
لدينا مفهومين في بايثون وهما Iterator و Iterable.  نعتبر أن ال Lists, tuples, dictionaries,set كائنات قابلة للتكرار وتعتبر حاويات متكررة "iterable containers" يمكنك الحصول على مكرر "Iterator " منها وحتى السلاسل Strings هي كائنات قابلة للتكرار، ويمكنك الحصول على مكرر منها. وجميعهم يمتلكون الطريقة ()iter التي تستخدم للحصول على مكرر Iterator منها:

li = ["argentena", "barca", "ali"]
iterator = iter(li)
print(next(iterator))
print(next(iterator))
print(next(iterator))
"""
argentena
barca
ali
"""

مثال عن String:

li = "argentena"
iterator = iter(li)
print(next(iterator))
print(next(iterator))
print(next(iterator))
"""
a
r
g
"""

يمكنك أيضاً المرور على عناصر المكرر من خلال الحلقات مثلاً:

li = "argentena"
iterator = iter(li)
for x in iterator:
  print(x) 
"""
a
r
g
e
n
t
e
n
a
"""

مثال عن tuple:

mytuple = ("apple", "banana", "cherry")
iterator = iter(mytuple)
for x in iterator:
  print(x) 
"""
apple
banana
cherry
"""

أما إذا أردنا إنشاء class كمكرر فيجب علينا تحقيق الطريقتين __iter __ () و __next __ () في الكائن الخاص بك. وكما نعلم جميعاً فإن الكائنات في بايثون تملك دالة (طريقة) تسمى __init __ () ، والتي تتيح لنا القيام بعمليات تهيئة عند إنشاء كائن من الصف. إن الدالة __iter __ ()  تعمل بشكل مشابه لها، حيث يمكنك القيام بالعمليات (التهيئة وما إلى ذلك) ، ولكن يجب دائماً إرجاع كائن المكرر نفسه.
أيضاً تسمح لك الدالة __next __ () بإجراء عمليات، ويجب أن تعيد العنصر التالي في التسلسل.مثال:

class num:
  def __iter__(self):
    self.i = 1
    return self  #التي تشير إلى الكائن نفسه self لاحظ أننا قمنا بإرجاع 

  def __next__(self):
    a = self.i
    self.i += 1
    return a

myclass = num()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
"""
1
2
3
4
"""
for i in myclass:
  print(i)
  if i==7:
    break
"""
1
2
3
4
1
2
3
4
5
6
7
"""

في المثال السابق ستستمر حلقة for إلى اللانهاية لو لم نضع break، لذا يمكننا استخدام StopIteration حيث نضيفها في طريقة __next __ () ، كشرط للإنهاء إذا تم التكرار لعدد محدد من المرات:

class num:
  def __iter__(self):
    self.i = 1
    return self  #التي تشير إلى الكائن نفسه self لاحظ أننا قمنا بإرجاع 

  def __next__(self):
    a = self.i
    self.i += 1
    return a

  def __next__(self):
    if self.i <= 10:
      a = self.i
      self.i += 1
      return a
    else:
      raise StopIteration
myclass = num()
for i in myclass:
  print(i)
"""
1
2
3
4
5
6
7
8
9
10
"""

هذا كل شيء تحتاجه عن المكررات.

  • 1
نشر

يمكن الاعتماد على المؤشر iterator: حيث نقوم ببناء الصنف بطريقة مشابهة للتالي:

class Counter(object):
  	# تهيئة العنصر
    def __init__(self, start, stop):
       self.start = start
       self.stop = stop
    # تعريف المؤشر
    def __iter__(self): return self
    # الدالة لجلب العنصر التالي
    def __next__(self): # next in Python 2
       # اختبار الشرط
       if self.start >= self.stop:
           raise StopIteration
       current = self.start * self.start
       self.start += 1
       return current

iterator = Counter(a, b)

ولجلب العنصر الحالي يمكن إضافة الدالة current التي تعيد start ألمعدلة:

def current(self):
       return self.start

وبطريقة أخرى:

كما يمكن الاستفادة من مفهوم المولد generator والكلمة المفتاحية yield:

def counter(start, stop):
    for i in range(start, stop):
        yield i
        
Counter = counter(3, 9)
  • 0
نشر

 

يمكنك عمل ذلك كالآتي

from datetime import timedelta, date

class DateIterable:

    def __init__(self, start_date, end_date):
        # تهيئة بداية ونهاية التواريخ
        self.start_date = start_date
        self.end_date = end_date
        self._present_day = start_date

    def __iter__(self):
        # إعادة الكائن
        # __iter__
        return self

    def __next__(self):
        # مقارنة التاريخ الحاضر مع التاريخ الأخير
        # إذا كان التاريخ الحاضر أكبر من التاريخ الأخير فسيتوقف التكرار
        if self._present_day >= self.end_date:
            raise StopIteration
        today = self._present_day
        self._present_day += timedelta(days=1)
        return today


if __name__ == '__main__':
    for day in DateIterable(date(2020, 1, 1), date(2020, 1, 6)):
        print(day)

أو يمكنك إضافة هذا الكود في الكائن

 def __iter__(self):
        for x in self.iterable:
            yield x

كما يلي

class someClass:
    def __init__(self,list):
        self.list = list
    def __iter__(self):
        for x in self.list:
            yield x


var = someClass([1,2,3,4,5])
for num in var: 
    print(num) 

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...