මම කැමතියි තව ටිකක් ආලෝකය විහිදුවන්න iter, __iter__සහ __getitem__තිර පිටුපස සිදුවන්නේ කුමක්ද යන්න. එම දැනුමෙන් සන්නද්ධව ඔබට කළ හැකි හොඳම දේ වන්නේ මන්දැයි ඔබට තේරුම් ගත හැකිය
try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')
මම පළමුව කරුණු ලැයිස්තුගත කර පසුව ඔබ forපයිතන් වල ලූපයක් භාවිතා කරන විට සිදුවන්නේ කුමක්ද යන්න පිළිබඳ ඉක්මන් මතක් කිරීමක් කර පසුව කරුණු නිදර්ශනය කිරීම සඳහා සාකච්ඡාවක් පවත්වමි.
කරුණු
- ඔබ යම් වස්තුවක් සිට iterator ලබා ගත හැක - oඇමතීම මගින්- iter(o)පහත කොන්දේසි අවම වශයෙන් එක් සත්ය නම්:
 
 අ)- oසතුව,- __iter__ක iterator වස්තුව නැවත වන ක්රමය. Iterator යනු- __iter__and සහ a- __next__(Python 2 :) ක්රමයක් ඇති ඕනෑම වස්තුවකි- next.
 
 ආ)- oසතුව- __getitem__ක්රමය.
 
- නිදසුනක් සඳහා - Iterableහෝ- Sequence, හෝ ගුණාංගය පරීක්ෂා කිරීම- __iter__ප්රමාණවත් නොවේ.
 
- වස්තුවක් නම් - oඋපකරණ පමණක්- __getitem__, නමුත්- __iter__,- iter(o)උත්සාහක දිනුම් සිට භාණ්ඩ ලබා ගැනීමට බව iterator ඉදි කරන- oදර්ශකය 0 ට ඇරඹෙන iterator පූර්ණ සංඛ්යාමය දර්ශකය ඕනෑම අල්ලා ඇත- IndexError(නමුත් වෙනත් කිසිදු දෝෂ) මතු පසුව මතු වන බව- StopIterationම.
 
- වඩාත් සාමාන්ය අර්ථයෙන් ගත් කල, - iterඑය නැවත උත්සාහ කළ තැනැත්තා විසින් නැවත ලබා දුන් අයෙක් පරීක්ෂා කර බැලීමට හැකියාවක් තිබේද යන්න පරීක්ෂා කිරීමට ක්රමයක් නොමැත .
 
- වස්තුවක් - oක්රියාත්මක කරන්නේ නම්- __iter__,- iterශ්රිතය මඟින් ආපසු ලබා දුන් වස්තුව- __iter__අනුකාරකයක් බව සහතික කරයි . වස්තුවක් පමණක් ක්රියාත්මක කරන්නේ දැයි සනීපාරක්ෂක පරීක්ෂණයක් නොමැත- __getitem__.
 
- __iter__ජය. වස්තුවක් නම්- oඋපකරණ දෙකම- __iter__හා- __getitem__,- iter(o)කියනු ඇත- __iter__.
 
- ඔබේම වස්තූන් නැවත ක්රියාත්මක කිරීමට අවශ්ය නම්, සෑම විටම - __iter__ක්රමය ක්රියාත්මක කරන්න .
 
for ලූප
ඉදිරියට යාම සඳහා, ඔබ forපයිතන් හි ලූපයක් භාවිතා කරන විට කුමක් සිදුවේද යන්න පිළිබඳ අවබෝධයක් අවශ්ය වේ. ඔබ දැනටමත් දන්නවා නම් ඊළඟ කොටසට දකුණට යාමට නිදහස් වන්න.
ඔබ for item in oකිසියම් ක්රියාකාරී වස්තුවක් සඳහා භාවිතා කරන විට o, පයිතන් ඇමතුම් ලබා iter(o)දෙන අතර ප්රතිලාභ අගය ලෙස iterator වස්තුවක් අපේක්ෂා කරයි. ඉරේටරයක් යනු __next__(හෝ nextපයිතන් 2) ක්රමයක් සහ __iter__ක්රමයක් ක්රියාත්මක කරන ඕනෑම වස්තුවකි .
සම්මුතිය අනුව, __iter__අනුකාරකයේ ක්රමය මඟින් වස්තුව නැවත ලබා දිය යුතුය (එනම් return self). පයිතන් පසුව ඉස්මතු වන nextතුරු StopIterationනැවත ක්රියාකරු අමතයි . මේ සියල්ල ව්යංගයෙන් සිදු වන නමුත් පහත දැක්වෙන නිරූපණය එය දෘශ්යමාන කරයි:
import random
class DemoIterable(object):
    def __iter__(self):
        print('__iter__ called')
        return DemoIterator()
class DemoIterator(object):
    def __iter__(self):
        return self
    def __next__(self):
        print('__next__ called')
        r = random.randint(1, 10)
        if r == 5:
            print('raising StopIteration')
            raise StopIteration
        return r
A ට වඩා අනුමාන කිරීම DemoIterable:
>>> di = DemoIterable()
>>> for x in di:
...     print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration
සාකච්ඡාව සහ නිදර්ශන
1 සහ 2 ලක්ෂ්යයන්හි: අනුකාරකයක් ලබා ගැනීම සහ විශ්වාස කළ නොහැකි චෙක්පත්
පහත පන්තිය සලකා බලන්න:
class BasicIterable(object):
    def __getitem__(self, item):
        if item == 3:
            raise IndexError
        return item
iterනිදසුනක් සමඟ ඇමතීම මඟින් ක්රියාත්මක වන BasicIterableබැවින් කිසිදු ගැටළුවක් නොමැතිව නැවත ක්රියා කරන්නෙකු ආපසු එනු ඇත .BasicIterable__getitem__
>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>
කෙසේ වෙතත්, එය බව සටහන් කිරීම වැදගත් වේ bද නැත __iter__විශේෂණය හා නිදසුනක් ලෙස සැලකේ Iterableහෝ Sequence:
>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False
ඒ නිසයි හොඳින් Python Luciano Ramalho විසින් ඉල්ලා නිර්දේශ iterහැකි සහ හැසිරවීමේ TypeErrorවස්තුවක් iterable දැයි පරීක්ෂා කිරීමට වඩාත්ම නිවැරදි ක්රමයක් ලෙස. පොතෙන් කෙලින්ම උපුටා දැක්වීම:
  පයිතන් 3.4 අනුව, වස්තුවක් නැවත xක්රියාත්මක කළ හැකිද යන්න පරීක්ෂා කිරීම සඳහා වඩාත් නිවැරදි ක්රමය නම්, ව්යතිරේකයක් නොමැති නම් එය ඇමතීම iter(x)සහ හැසිරවීමයි TypeError. මෙය භාවිතයට වඩා නිරවද්ය ය isinstance(x, abc.Iterable), මන්ද යත් iter(x), උරුමය __getitem__ක්රමය ද සලකා බලන අතර Iterableඒබීසී එසේ නොකරයි.
කරුණු 3 මත: එකම සපයන වස්තූන් එල්ලාවල මහතා __getitem__, නමුත්__iter__
BasicIterableඅපේක්ෂිත පරිදි කෘති නිදසුනක් උපුටා දැක්වීම: පයිතන් දර්ශකයක් මඟින් අයිතම ලබා ගැනීමට උත්සාහ කරන අනුකාරකයක් සාදයි, එය බිංදුවෙන් පටන් ගෙන, IndexErrorමතු වන තුරු . ආදර්ශන වස්තුවෙහි __getitem__ක්රමය මඟින් නැවත itemලබා __getitem__(self, item)දුන් අනුකාරකය විසින් තර්කය ලෙස සැපයූ දේ ආපසු ලබා දේ iter.
>>> b = BasicIterable()
>>> it = iter(b)
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
StopIterationඊලඟ අයිතමය ආපසු ලබා දිය නොහැකි වූ විට අනුකාරකය මතු වන බවත්, IndexErrorඒ සඳහා මතු කර item == 3ඇති දේ අභ්යන්තරව හසුරුවන බවත් සලකන්න . මේ නිසා ලූපයක් BasicIterableසමඟ forලූපයක් බලාපොරොත්තු වන පරිදි ක්රියා කරයි:
>>> for x in b:
...     print(x)
...
0
1
2
iterදර්ශකය මඟින් අයිතම වෙත ප්රවේශ වීමට උත්සාහ කරන්නන් විසින් නැවත ලබා දුන් ආකාරය පිළිබඳ සංකල්පය ගෙදර ගෙන යාම සඳහා තවත් උදාහරණයක් මෙන්න . WrappedDictඋරුම නොවේ dict, එයින් අදහස් වන්නේ නිදසුන් සඳහා __iter__ක්රමයක් නොමැති බවයි .
class WrappedDict(object): # note: no inheritance from dict!
    def __init__(self, dic):
        self._dict = dic
    def __getitem__(self, item):
        try:
            return self._dict[item] # delegate to dict.__getitem__
        except KeyError:
            raise IndexError
ඇමතුම් __getitem__පවරනු dict.__getitem__ලබන්නේ වර්ග වරහන් අංකනය හුදෙක් කෙටිමං සඳහා වන බව සලකන්න .
>>> w = WrappedDict({-1: 'not printed',
...                   0: 'hi', 1: 'StackOverflow', 2: '!',
...                   4: 'not printed', 
...                   'x': 'not printed'})
>>> for x in w:
...     print(x)
... 
hi
StackOverflow
!
4 වන සහ 5 වන ස්ථානවල: iterඅනුකාරකයක් ඇමතූ විට එය පරීක්ෂා කරයි__iter__ :
විට iter(o)වස්තුවක් ඉල්ලා සිටී o, iterනැවත අගය බවට වග බලා ගන්න වනු ඇත __iter__, මෙම ක්රමය දැනට නම්, යම් iterator වේ. මෙයින් අදහස් කරන්නේ ආපසු ලබා දුන් වස්තුව ක්රියාත්මක කළ යුතු බවයි __next__(හෝ nextපයිතන් 2 හි) සහ __iter__. iterසපයන වස්තූන් සඳහා කිසිදු සනීපාරක්ෂක පරීක්ෂණයක් සිදු කළ නොහැක __getitem__, මන්ද එය පූර්ණ සංඛ්යා දර්ශකයෙන් වස්තුවේ අයිතමවලට ප්රවේශ විය හැකිද යන්න පරීක්ෂා කිරීමට ක්රමයක් නොමැති බැවිනි.
class FailIterIterable(object):
    def __iter__(self):
        return object() # not an iterator
class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception
FailIterIterableඋදාහරණ වලින් අනුකාරකයක් තැනීම ක්ෂණිකව අසමත් වන අතර, අනුකාරකයක් තැනීම FailGetItemIterableසාර්ථක වන නමුත් පළමු ඇමතුමට ව්යතිරේකයක් දමනු ඇත __next__.
>>> fii = FailIterIterable()
>>> iter(fii)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'object'
>>>
>>> fgi = FailGetitemIterable()
>>> it = iter(fgi)
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/iterdemo.py", line 42, in __getitem__
    raise Exception
Exception
6 වන කරුණ: __iter__ජය
මෙය සරල ය. වස්තුවක උපකරණ නම් __iter__හා __getitem__, iterකියනු ඇත __iter__. පහත පන්තිය සලකා බලන්න
class IterWinsDemo(object):
    def __iter__(self):
        return iter(['__iter__', 'wins'])
    def __getitem__(self, item):
        return ['__getitem__', 'wins'][item]
සහ නිදසුනක් මත ලූප කිරීමේදී ප්රතිදානය:
>>> iwd = IterWinsDemo()
>>> for x in iwd:
...     print(x)
...
__iter__
wins
7 වන කරුණ: ඔබේ නැවත ක්රියාත්මක කළ හැකි පන්ති ක්රියාත්මක කළ යුතුය __iter__
බොහෝ builtin අනුක්රමය කැමති ඇයි ඔබ ඇසිය හැක listමෙරට ක්රියාත්මක __iter__වන විට ක්රමය __getitem__ප්රමාණවත් වනු ඇත.
class WrappedList(object): # note: no inheritance from list!
    def __init__(self, lst):
        self._list = lst
    def __getitem__(self, item):
        return self._list[item]
සියල්ලට පසු, (පංති වරහන් අංකනය භාවිතා කරමින්) ඇමතුම් ලබා __getitem__දෙන ඉහත පන්තියේ අවස්ථා පිළිබඳ නැවත list.__getitem__කියවීම හොඳින් ක්රියාත්මක වේ:
>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
...     print(x)
... 
A
B
C
ඔබගේ අභිරුචි පුනරාවර්තනයන් ක්රියාත්මක කළ යුතු හේතු __iter__පහත පරිදි වේ:
- ඔබ ක්රියාත්මක කරන්නේ නම් __iter__, නිදසුන් පුනරාවර්තන ලෙස සලකනුisinstance(o, collections.abc.Iterable)ලබන අතර නැවත පැමිණේTrue.
- ආපසු ලබා දුන් වස්තුව __iter__අනුකාරකයක් නොවේ නම්,iterවහාම අසමත් වී a මතු කරයිTypeError.
- __getitem__පසුගාමී අනුකූලතා හේතූන් මත විශේෂ හැසිරවීම පවතී. චතුර ලෙස පයිතන් වෙතින් නැවත උපුටා දැක්වීම:
  ඕනෑම පයිතන් අනුක්රමයක් නැවත ක්රියාත්මක කළ හැක්කේ එබැවිනි: ඒවා සියල්ලම ක්රියාත්මක __getitem__වේ. ඇත්ත වශයෙන්ම, සම්මත අනුක්රමයන් ද ක්රියාත්මක වන අතර __iter__, ඔබත් එසේ කළ යුතුය, මන්දයත් විශේෂ හැසිරවීම __getitem__පසුගාමී අනුකූලතා හේතූන් මත පවතින අතර අනාගතයේ දී එය නැති වී යා හැකිය (මා මෙය ලියන විට එය ප්රතික්ෂේප නොකළද).
               
              
__getitem__වස්තුවක් නැවත සැකසීමට ද ප්රමාණවත් වේ