पायथन में, मैं कैसे निर्धारित करूं कि कोई वस्तु चलने योग्य है?


1083

क्या कोई तरीका पसंद है isiterable? अब तक मैंने जो एकमात्र समाधान खोजा है, वह है

hasattr(myObj, '__iter__')

लेकिन मुझे यकीन नहीं है कि यह कितना मूर्खतापूर्ण है।


18
__getitem__किसी वस्तु को चलने योग्य बनाने के लिए भी पर्याप्त है
कोस

4
एफडब्ल्यूआईडब्ल्यू: iter(myObj)सफल होता है isinstance(myObj, dict), इसलिए यदि आप देख रहे हैं myObjकि dictएस या एकल का अनुक्रम हो सकता है dict, तो आप दोनों मामलों में सफल होंगे। एक सूक्ष्मता जो महत्वपूर्ण है यदि आप जानना चाहते हैं कि एक अनुक्रम क्या है और क्या नहीं है। (अजगर 2 में)
बेन मोशर

7
__getitem__एक वस्तु को चलने योग्य बनाने के लिए भी पर्याप्त है ... यदि यह शून्य सूचकांक पर शुरू होता है
कार्लोस ए। गोमेज़

जवाबों:


26

मैं इस समस्या का हाल ही में थोड़ा अध्ययन कर रहा हूं। उसके आधार पर मेरा निष्कर्ष है कि आजकल यह सबसे अच्छा तरीका है:

from collections.abc import Iterable   # drop `.abc` with Python 2.7 or lower

def iterable(obj):
    return isinstance(obj, Iterable)

उपरोक्त की सिफारिश पहले ही की जा चुकी है, लेकिन आम सहमति यह रही है कि इसका उपयोग iter()करना बेहतर होगा:

def iterable(obj):
    try:
        iter(obj)
    except Exception:
        return False
    else:
        return True

हमने iter()इस उद्देश्य के लिए अपने कोड में भी उपयोग किया है, लेकिन मैंने हाल ही में उन वस्तुओं से अधिक से अधिक परेशान होना शुरू कर दिया है, जिन्हें केवल उपयोग करने योग्य __getitem__माना जा रहा है। __getitem__गैर-चलने योग्य ऑब्जेक्ट में होने के लिए वैध कारण हैं और उनके साथ उपरोक्त कोड अच्छी तरह से काम नहीं करता है। एक वास्तविक जीवन उदाहरण के रूप में हम Faker का उपयोग कर सकते हैं । उपरोक्त कोड इसे पुनरावृत्त होने की रिपोर्ट करता है, लेकिन वास्तव में इसे पुनरावृत्त करने की कोशिश करता है एक कारण बनता है AttributeError(Faker 4.0.2 के साथ परीक्षण)

>>> from faker import Faker
>>> fake = Faker()
>>> iter(fake)    # No exception, must be iterable
<iterator object at 0x7f1c71db58d0>
>>> list(fake)    # Ooops
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/.../site-packages/faker/proxy.py", line 59, in __getitem__
    return self._factory_map[locale.replace('-', '_')]
AttributeError: 'int' object has no attribute 'replace'

यदि हम उपयोग करते हैं insinstance(), तो हम गलती से Faker उदाहरणों पर विचार नहीं करेंगे (या किसी भी अन्य वस्तुएं __getitem__) केवल चलने योग्य होने के लिए:

>>> from collections.abc import Iterable
>>> from faker import Faker
>>> isinstance(Faker(), Iterable)
False

पहले के जवाबों में टिप्पणी की गई थी कि iter()पायथन में पुनरावृत्ति को लागू करने का पुराना तरीका सुरक्षित है, इस पर आधारित था __getitem__और isinstance()दृष्टिकोण यह पता नहीं लगाएगा। यह पुराने पाइथन संस्करणों के साथ सच हो सकता है, लेकिन isinstance()आजकल मेरे बहुत संपूर्ण परीक्षण पर आधारित है। एकमात्र मामला जहां isinstance()काम नहीं iter()किया था, लेकिन UserDictपायथन 2 का उपयोग करते समय साथ था । यदि यह प्रासंगिक है, तो इसे isinstance(item, (Iterable, UserDict))कवर करने के लिए उपयोग करना संभव है ।


1
इसके अलावा typing.Dictइसे पुनरावृत्ति माना जाता है iter(Dict)लेकिन list(Dict)त्रुटि के साथ विफल रहता है TypeError: Parameters to generic types must be types. Got 0.। जैसा कि उम्मीद थी कि isinstance(Dict, Iterable)झूठे हैं।
पेक्का क्लर्क

1
मैं एक ही निष्कर्ष पर आया था, लेकिन विभिन्न कारणों से। का उपयोग कर iterहमारे कोड है कि "पूर्व कैशिंग" का इस्तेमाल किया अनावश्यक रूप से धीमा करने के लिए में से कुछ का कारण बना। यदि __iter__कोड धीमा है, तो कॉलिंग iter... किसी भी समय आप यह देखना चाहते हैं कि क्या कुछ चलने योग्य है।
थरवलेन

842
  1. __iter__अनुक्रम प्रकार पर काम करता है के लिए जाँच , लेकिन यह पायथन 2 में जैसे उदाहरण पर विफल होगा । मैं सही उत्तर भी जानना चाहूंगा, तब तक, यहाँ एक संभावना है (जो कि तार पर भी काम करेगी):

    from __future__ import print_function
    
    try:
        some_object_iterator = iter(some_object)
    except TypeError as te:
        print(some_object, 'is not iterable')

    iterके लिए निर्मित की जाँच करता __iter__विधि या तार के मामले में __getitem__विधि।

  2. एक अन्य सामान्य पाइथोनिक दृष्टिकोण एक पुनरावृत्त को मानने के लिए है, फिर अगर वह दी गई वस्तु पर काम नहीं करता है तो इनायत करें। पायथन शब्दावली:

    पाइथोनिक प्रोग्रामिंग शैली जो किसी प्रकार की वस्तु से स्पष्ट संबंध के बजाय अपनी विधि या विशेषता हस्ताक्षर के निरीक्षण द्वारा किसी वस्तु के प्रकार को निर्धारित करती है ("अगर यह बतख की तरह दिखती है और बतख की तरह बत्तख की तरह , तो यह एक बतख होनी चाहिए ।") इंटरफेस पर जोर देने से। विशिष्ट प्रकारों के बजाय, अच्छी तरह से डिज़ाइन किया गया कोड बहुरूपी प्रतिस्थापन की अनुमति देकर इसके लचीलेपन में सुधार करता है। डक-टाइपिंग प्रकार () या आइंस्टीन () का उपयोग करके परीक्षणों से बचा जाता है। इसके बजाय, यह आम तौर पर प्रोग्रामिंग की ईएएफपी (ईज़ी टू आस्क फॉरग्विजेंस टू परमिशन) शैली को नियोजित करता है।

    ...

    try:
       _ = (e for e in my_object)
    except TypeError:
       print my_object, 'is not iterable'
  3. collectionsमॉड्यूल जो वर्ग या उदाहरणों पूछने के लिए अगर वे विशेष सुविधा प्रदान करती हैं, उदाहरण के लिए अनुमति देने के कुछ सार आधार वर्ग, प्रदान करता है:

    from collections.abc import Iterable
    
    if isinstance(e, Iterable):
        # e is iterable

    हालाँकि, यह उन वर्गों के लिए जाँच नहीं करता है जो इसके माध्यम से चलने योग्य हैं __getitem__


34
[e for e in my_object]अन्य कारणों से अपवाद बढ़ा सकता है, यानी कार्यान्वयन my_objectमें अपरिभाषित या संभावित बग my_object
निक डंडौलिसिस

37
एक स्ट्रिंग है एक दृश्य ( isinstance('', Sequence) == True) और किसी भी क्रम के रूप में यह है iterable ( isinstance('', Iterable))। हालांकि hasattr('', '__iter__') == Falseऔर यह भ्रामक हो सकता है।
jfs

82
यदि my_objectबहुत बड़ी है (कहो, अनंत की तरह itertools.count()) आपकी सूची की समझ में बहुत समय लगेगा / स्मृति। एक जनरेटर बनाने के लिए बेहतर है, जो कभी भी (संभावित अनंत) सूची बनाने की कोशिश नहीं करेगा।
क्रिस लूत्ज

14
क्या होगा अगर some_object फेंकता है TypeError अन्य कारण (बग आदि) के कारण भी? हम इसे "Noterable TypeError" से कैसे बता सकते हैं?
शौंग सेप

54
ध्यान दें कि पायथन 3: hasattr(u"hello", '__iter__')रिटर्नTrue
कार्लोस

572

बतख टाइपिंग

try:
    iterator = iter(theElement)
except TypeError:
    # not iterable
else:
    # iterable

# for obj in iterator:
#     pass

प्रकार की जाँच

एब्सट्रैक्ट बेस क्लासेस का उपयोग करें । उन्हें कम से कम अजगर 2.6 की जरूरत है और केवल नई शैली की कक्षाओं के लिए काम करना चाहिए।

from collections.abc import Iterable   # import directly from collections for Python < 3.3

if isinstance(theElement, Iterable):
    # iterable
else:
    # not iterable

हालाँकि, प्रलेखन द्वाराiter() वर्णित थोड़ा अधिक विश्वसनीय है :

जाँच करना उन isinstance(obj, Iterable)वर्गों का पता लगाता है जो Iterable के रूप में पंजीकृत हैं या जिनके पास एक __iter__()विधि है, लेकिन यह उन वर्गों का पता नहीं लगाता है जो __getitem__() विधि के साथ पुनरावृति करते हैं । यह निर्धारित करने का एकमात्र विश्वसनीय तरीका है कि कोई वस्तु कॉल करने योग्य है या नहीं iter(obj)


18
Luciano Ramalho द्वारा "धाराप्रवाह पायथन" से: पायथन 3.4 के रूप में, यह जांचने का सबसे सटीक तरीका है कि क्या कोई ऑब्जेक्ट x iterable है iter (x) को कॉल करना है और यह नहीं होने पर TypeError अपवाद को संभालना है। यह आइंस्टीन (x, abc.Iterable) का उपयोग करने से अधिक सटीक है, क्योंकि iter (x) भी विरासत गेटिटम विधि को मानता है, जबकि Iterable ABC नहीं करता है।
RdB

यदि आप सोच रहे हैं "ओह, मैं सिर्फ isinstance(x, (collections.Iterable, collections.Sequence))इसके बजाय iter(x)", ध्यान दें कि यह अभी भी एक चलने योग्य वस्तु का पता नहीं लगाएगा जो केवल लागू करता है __getitem__लेकिन नहीं __len__iter(x)अपवाद का उपयोग करें और पकड़ें।
डेल

आपका दूसरा उत्तर काम नहीं करता है। प्यूनो में अगर मैं करता हूं iter(slide1), तो सब ठीक हो जाता है, हालांकि isinstance(slide1, Iterable)फेंकता है TypeError: issubclass() arg 1 must be a class
हाय-एंजेल

@ हाय-एंजेल एक बग की तरह लगता है PyUNOकि आपका त्रुटि संदेश issubclass()इसके बजाय कहता है isinstance()
जॉर्ज शॉली

2
किसी ऑब्जेक्ट पर iter () कॉल करना एक महंगा ऑपरेशन हो सकता है (Pytorch में DataLoader देखें, जो iter () पर कई प्रक्रियाओं को फोर्क / स्पॉन्ज करता है)।
सज़ाली

125

मैं इंटरप्ले पर थोड़ा और अधिक प्रकाश डालना चाहता हूं iter, __iter__और __getitem__पर्दे के पीछे क्या होता है। उस ज्ञान से लैस, आप यह समझने में सक्षम होंगे कि आप सबसे अच्छा क्यों कर सकते हैं

try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')

मैं पहले तथ्यों को सूचीबद्ध करूंगा और फिर एक त्वरित अनुस्मारक के साथ पालन करूंगा कि जब आप नौकरी करते हैं तो क्या होता है for अजगर में लूप , तो तथ्यों को चित्रित करने के लिए चर्चा के बाद।

तथ्य

  1. आप oकॉल करके किसी भी ऑब्जेक्ट से एक iterator प्राप्त कर सकते हैं iter(o)यदि निम्न में से कम से कम एक स्थिति सही है:

    a) के oपास एक __iter__विधि है जो इट्रेटर ऑब्जेक्ट लौटाता है। एक पुनरावृत्त एक __iter__और __next__(पायथन 2:) nextविधि के साथ कोई भी वस्तु है ।

    b) oकी एक __getitem__विधि है।

  2. उदाहरण के लिए Iterableया Sequenceविशेषता के लिए जाँच करना __iter__पर्याप्त नहीं है।

  3. यदि कोई वस्तु oकेवल लागू होती है __getitem__, लेकिन नहीं __iter__, iter(o)तो एक पुनरावृत्ति का निर्माण होगा जो oपूर्णांक सूचकांक से आइटम लाने की कोशिश करता है , सूचकांक 0. पर शुरू होता है। इट्रेटर किसी भी IndexError(लेकिन कोई अन्य त्रुटियों) को नहीं उठाएगा और फिर StopIterationखुद को उठाता है।

  4. सबसे सामान्य अर्थों में, यह जांचने का कोई तरीका नहीं है कि क्या इट्रेटर द्वारा वापस लौटाया गया iterहै या नहीं।

  5. यदि कोई ऑब्जेक्ट oलागू होता है __iter__, तो iterफ़ंक्शन यह सुनिश्चित करेगा कि ऑब्जेक्ट द्वारा लौटाया गया __iter__एक पुनरावृत्ति है। यदि कोई वस्तु केवल लागू होती है तो कोई पवित्रता जांच नहीं है __getitem__

  6. __iter__जीतता है। यदि कोई ऑब्जेक्ट oदोनों को लागू करता है __iter__और __getitem__, iter(o)कॉल करेगा __iter__

  7. यदि आप अपनी खुद की वस्तुओं को चलने योग्य बनाना चाहते हैं, तो हमेशा __iter__विधि को लागू करें ।

for छोरों

साथ पालन करने के लिए, आपको यह समझने की आवश्यकता है कि जब आप forपायथन में एक लूप को नियुक्त करते हैं तो क्या होता है । यदि आप पहले से ही जानते हैं तो अगले भाग पर सीधे जाने के लिए स्वतंत्र महसूस करें।

जब आप for item in oकिसी पुनरावृत्त वस्तु के लिए उपयोग करते हैं o, तो पायथन कॉल करता है iter(o)और वापसी मूल्य के रूप में एक पुनरावृत्त वस्तु की अपेक्षा करता है। एक पुनरावृत्त कोई वस्तु है जो __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

इस पर परिवर्तन 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

यही कारण है कि लुसियानो रामलहो द्वारा फ्लुएंट पायथन कॉल करने iterऔर संभावित TypeErrorको संभालने के लिए सबसे सटीक तरीका है जो यह जांचने की सलाह देता है कि क्या कोई ऑब्जेक्ट चलने योग्य है। पुस्तक से सीधे उद्धरण:

पायथन 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__यदि विधि मौजूद है, तो रिटर्न वैल्यू , इट्रेटर है। इसका मतलब है कि लौटी हुई वस्तु को लागू करना चाहिए __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__

आप अपने आप से पूछ सकते हैं कि अधिकांश बिलियन अनुक्रम 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__इस प्रकार हैं:

  1. यदि आप लागू करते हैं __iter__, तो इंस्टेंसेस को पुनरावृत्त माना isinstance(o, collections.abc.Iterable)जाएगा , और वापस आ जाएगा True
  2. यदि द्वारा दी गई वस्तु __iter__एक पुनरावृत्ति नहीं है, iterतो तुरंत विफल हो जाएगी और ए बढ़ाएगी TypeError
  3. __getitem__पश्चगामी संगतता कारणों के लिए विशेष हैंडलिंग मौजूद है। धाराप्रवाह पायथन से फिर से उद्धृत:

यही कारण है कि किसी भी पायथन अनुक्रम चलने योग्य है: वे सभी लागू करते हैं __getitem__। वास्तव में, मानक क्रम भी लागू होता है __iter__, और आपका भी होना चाहिए, क्योंकि __getitem__पिछड़े संगतता कारणों के लिए विशेष हैंडलिंग मौजूद है और भविष्य में चली जा सकती है (हालांकि यह जैसा कि मैं इसे लिखता हूं, यह पदावनत नहीं है)।


इसलिए यह एक विधेय को परिभाषित करने के लिए सुरक्षित है is_iterableलौटाकर Trueमें tryब्लॉक और Falseमें except TypeErrorब्लॉक?
अलंकालविटि

यह एक बेहतरीन जवाब है। मुझे लगता है कि यह गेटिटेम प्रोटोकॉल के अनपेक्षित और दुर्भाग्यपूर्ण प्रकृति को उजागर करता है। इसे कभी नहीं जोड़ा जाना चाहिए था।
नील जी

31

यह पर्याप्त नहीं है: वस्तु द्वारा लौटाई गई वस्तु __iter__पुनरावृत्ति प्रोटोकॉल (अर्थात nextविधि) को लागू करना चाहिए । दस्तावेज़ में संबंधित अनुभाग देखें

पायथन में, एक अच्छा अभ्यास "चेकिंग" के बजाय "कोशिश करना और देखना" है।


9
"बतख टाइपिंग" मुझे विश्वास है? :)
विलेम

9
@willem: या ;-) "अनुमति के लिए लेकिन माफी नहीं मांगते"
jldupont

14
@willem "अनुमति" और "क्षमा" शैली दोनों ही बतख टाइपिंग के रूप में योग्य हैं। आप क्या कर सकते हैं एक वस्तु पूछते हैं करना नहीं बल्कि यह क्या की तुलना में है , कि के बतख टाइपिंग। यदि आप आत्मनिरीक्षण का उपयोग करते हैं, तो यह "अनुमति" है; यदि आप इसे करने की कोशिश करते हैं और देखते हैं कि यह काम करता है या नहीं, तो यह "माफी" है।
मार्क रीड

22

पायथन <= 2.5 में, आप नहीं कर सकते हैं और नहीं - यह एक "अनौपचारिक" इंटरफ़ेस था।

लेकिन पायथन 2.6 और 3.0 के बाद से आप कुछ एबीसी (एब्सट्रैक्ट बेस क्लास) इंफ्रास्ट्रक्चर के साथ-साथ कुछ बिलियन एबीसी का भी लाभ उठा सकते हैं जो संग्रह मॉड्यूल में उपलब्ध हैं:

from collections import Iterable

class MyObject(object):
    pass

mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)

print isinstance("abc", Iterable)

अब, यह वांछनीय है या वास्तव में काम करता है, यह सिर्फ सम्मेलनों की बात है। जैसा कि आप देख सकते हैं, आप कर सकते हैं एक गैर-चलने योग्य वस्तु को Iterable के रूप में पंजीकृत - और यह रनटाइम पर एक अपवाद को बढ़ाएगा। इसलिए, आइंस्टीन एक "नया" अर्थ प्राप्त करता है - यह सिर्फ "घोषित" प्रकार की संगतता के लिए जांचता है, जो पायथन में जाने का एक अच्छा तरीका है।

दूसरी ओर, यदि आपकी वस्तु आपको आवश्यक इंटरफ़ेस को संतुष्ट नहीं करती है, तो आप क्या करने जा रहे हैं? निम्नलिखित उदाहरण लें:

from collections import Iterable
from traceback import print_exc

def check_and_raise(x):
    if not isinstance(x, Iterable):
        raise TypeError, "%s is not iterable" % x
    else:
        for i in x:
            print i

def just_iter(x):
    for i in x:
        print i


class NotIterable(object):
    pass

if __name__ == "__main__":
    try:
        check_and_raise(5)
    except:
        print_exc()
        print

    try:
        just_iter(5)
    except:
        print_exc()
        print

    try:
        Iterable.register(NotIterable)
        ni = NotIterable()
        check_and_raise(ni)
    except:
        print_exc()
        print

यदि ऑब्जेक्ट आपकी अपेक्षाओं को पूरा नहीं करता है, तो आप सिर्फ एक टाइप-इयरर को फेंक देते हैं, लेकिन यदि उचित एबीसी पंजीकृत किया गया है, तो आपका चेक बेकार है। इसके विपरीत, यदि__iter__ विधि उपलब्ध है तो पायथन स्वचालित रूप से उस कक्षा की वस्तु को Iterable होने के रूप में पहचान लेगा।

इसलिए, यदि आप सिर्फ एक पुनरावृत्ति की उम्मीद करते हैं, तो उस पर पुनरावृति करें और इसे भूल जाएं। दूसरी ओर, यदि आपको इनपुट प्रकार के आधार पर अलग-अलग चीजें करने की आवश्यकता है, तो आपको एबीसी अवसंरचना बहुत उपयोगी लग सकती है।


13
except:शुरुआती के लिए उदाहरण कोड में नंगे का उपयोग न करें । यह बुरे अभ्यास को बढ़ावा देता है।
jfs

JFS: मैं नहीं करूंगा, लेकिन मुझे कई अपवाद-बढ़ाने वाले कोड से गुजरने की आवश्यकता थी और मैं विशिष्ट अपवाद को पकड़ना नहीं चाहता था ... मुझे लगता है कि इस कोड का उद्देश्य बहुत स्पष्ट है।
एलन फ्रांजोनी

21
try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable

यह देखने के लिए चेक न चलाएं कि क्या आपका बत्तख वास्तव में एक बत्तख है या नहीं यह देखने के लिए कि क्या यह चलने योग्य है या नहीं, इसे मानो और यदि यह नहीं था तो शिकायत करें।


3
तकनीकी रूप से, पुनरावृत्ति के दौरान आपकी गणना एक फेंक सकती है TypeErrorऔर आपको यहां फेंक सकती है, लेकिन मूल रूप से हाँ।
क्रिस लूत्ज

6
@ विलेम: बेंचमार्क करने के लिए कृपया समय-सीमा का उपयोग करें। पायथन अपवाद अक्सर बयानों की तुलना में तेज़ होते हैं। वे दुभाषिया के माध्यम से थोड़ा छोटा रास्ता अपना सकते हैं।
S.Lott

2
@ विलेम: आयरनप्यटन में धीमी गति से (सीपीथॉन की तुलना में) अपवाद हैं।
jfs

2
एक काम करने की कोशिश: बयान वास्तव में तेज है। इसलिए यदि आपके पास कुछ अपवाद हैं, तो प्रयास-अपवाद तेज है। यदि आप कई अपवादों की उम्मीद करते हैं, तो "यदि" तेज हो सकता है।
अर्ने बाबोनहॉसरहाइड

2
क्या अपवाद वस्तु को " as e" जोड़ने के TypeErrorबजाय " " जोड़कर नहीं पकड़ा जाना चाहिए , e?
HelloGoodbye

21

पायथन 3.5 के बाद से आप टाइपिंग से संबंधित चीजों के लिए मानक लाइब्रेरी से टाइपिंग मॉड्यूल का उपयोग कर सकते हैं:

from typing import Iterable

...

if isinstance(my_item, Iterable):
    print(True)

18

अब तक मुझे मिला सबसे अच्छा समाधान:

hasattr(obj, '__contains__')

जो मूल रूप से जाँचता है कि ऑब्जेक्ट inऑपरेटर को लागू करता है या नहीं ।

लाभ (किसी भी अन्य समाधान में तीनों नहीं हैं):

  • यह एक अभिव्यक्ति है ( मेमने के रूप में काम करता है , कोशिश के विपरीत ... संस्करण को छोड़कर )
  • यह है सब iterables द्वारा कार्यान्वित (होना चाहिए), सहित तार (करने के लिए विरोध के रूप में __iter__)
  • किसी भी अजगर पर काम करता है> = 2.5

टिप्पणियाँ:

  • "माफ़ी माँगना, क्षमा न करना" का पायथन दर्शन एक अच्छी तरह से काम नहीं करता है जब एक सूची में उदाहरण के लिए आपके पास पुनरावृत्तियाँ और गैर-पुनरावृत्तियाँ हैं और आपको इसके प्रकार के अनुसार प्रत्येक तत्व को अलग तरह से व्यवहार करने की आवश्यकता है (कोशिश और गैर पर पुनरावृत्तियों का इलाज करना) काम को छोड़कर iterables काम करेगा , लेकिन यह बट-बदसूरत और भ्रामक लगेगा)
  • इस समस्या का समाधान जो वास्तव में वस्तु पर पुनरावृति करने का प्रयास करता है (उदाहरण के लिए [एक्स में एक्स के लिए obj]) यह जांचने के लिए कि क्या यह चलने योग्य है, बड़े पुनरावृत्तियों के लिए महत्वपूर्ण प्रदर्शन दंड को प्रेरित कर सकता है (विशेषकर यदि आपको बस पुनरावृत्ति के पहले कुछ तत्वों की आवश्यकता है, तो) उदाहरण) और बचा जाना चाहिए

3
अच्छा है, लेकिन स्टैकओवरफ्लो. com/questions/ 1952464/… में प्रस्तावित संग्रह मॉड्यूल का उपयोग क्यों नहीं करते हैं ? मुझे अधिक अभिव्यंजक लगता है।
डेव अब्राहम

1
यह कम है (और अतिरिक्त आयात की आवश्यकता नहीं है) किसी भी स्पष्टता को खोए बिना: एक "समाहित" विधि होने से यह जांचने के लिए एक प्राकृतिक तरीके की तरह महसूस होता है कि क्या कुछ वस्तुओं का संग्रह है।
व्लाद

46
सिर्फ इसलिए कि कुछ हो सकता है कुछ जरूरी नहीं कि इसका मतलब यह है कि यह चलने योग्य है। उदाहरण के लिए, एक उपयोगकर्ता जांच कर सकता है कि एक बिंदु 3 डी क्यूब में है, लेकिन आप इस ऑब्जेक्ट के माध्यम से कैसे पुनरावृति करेंगे?
केसी कुबाल

13
यह गलत है। एक iterable ही समर्थन नहीं करता है शामिल कम से कम अजगर 3.4 के साथ,।
पीटर शिनियर्स

15

आप यह कोशिश कर सकते हैं:

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return False

यदि हम एक जनरेटर बना सकते हैं जो उस पर पुनरावृत्त करता है (लेकिन कभी भी जनरेटर का उपयोग न करें तो यह स्थान नहीं लेता है), यह चलने योग्य है। एक "डुह" तरह की चीज लगती है। आपको यह निर्धारित करने की आवश्यकता है कि क्या एक चर पहले स्थान पर चलने योग्य है?


किस बारे में iterable(itertools.repeat(0))? :)
badp

5
@badp, (x for x in a)बस एक जनरेटर बनाता है, यह किसी पर कोई पुनरावृत्ति नहीं करता है।
कैचमेईटाउट्री

5
क्या कोशिश करना (x for x in a)ठीक कोशिश के बराबर है iterator = iter(a)? या कुछ ऐसे मामले हैं जिनमें दोनों अलग-अलग हैं?
अधिकतम

for _ in a: breakअधिक सीधा नहीं है ? क्या यह धीमा है?
Mr_and_Mrs_D

2
@Mr_and_Mrs_D कि खराब है अगर परीक्षण की गई वस्तु एक एटरेटर है जिसे बाद में पुनरावृत्त किया जाता है (यह 1 आइटम छोटा होगा क्योंकि यह स्थिति रीसेट नहीं की जा सकती है), कचरा जनरेटर बनाने से ऑब्जेक्ट पर पुनरावृति नहीं होती है क्योंकि वे ओवररेटेड नहीं होते हैं, हालांकि मुझे यकीन नहीं है कि यह 100% एक टाइप-इयरर को बढ़ाएगा यदि यह चलने योग्य नहीं है।
Tcll

13

मुझे यहाँ एक अच्छा समाधान मिला :

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)

10

पायथन 2 शब्दावली के अनुसार , पुनरावृत्तियाँ हैं

सभी अनुक्रम प्रकार (जैसे list, str, और tuple) और जैसे कुछ गैर अनुक्रम प्रकार dictऔर fileऔर किसी भी कक्षा आप एक साथ परिभाषित की वस्तुओं __iter__()या __getitem__()विधि। Iterables का उपयोग लूप के लिए और कई अन्य स्थानों पर किया जा सकता है जहां अनुक्रम की आवश्यकता होती है (ज़िप (), मानचित्र (), ...)। जब एक चलने योग्य ऑब्जेक्ट को अंतर्निहित फ़ंक्शन iter () के तर्क के रूप में पारित किया जाता है, तो यह ऑब्जेक्ट के लिए एक पुनरावृत्ति देता है।

बेशक, इस तथ्य के आधार पर पायथन के लिए सामान्य कोडिंग शैली को देखते हुए कि यह "अनुमति की तुलना में माफी मांगने में आसान है।", सामान्य अपेक्षा का उपयोग करना है।

try:
    for i in object_in_question:
        do_something
except TypeError:
    do_something_for_non_iterable

लेकिन अगर आपको इसे स्पष्ट रूप से जांचने की आवश्यकता है, तो आप इसके द्वारा पुनरावृत्ति के लिए परीक्षण कर सकते हैं hasattr(object_in_question, "__iter__") or hasattr(object_in_question, "__getitem__")। आपको दोनों की जांच करने की आवश्यकता है, क्योंकि strएस में एक __iter__विधि नहीं है (कम से कम पायथन 2 में नहीं है, पायथन 3 में वे करते हैं) और क्योंकि generatorऑब्जेक्ट में __getitem__विधि नहीं है ।


8

मैं अक्सर अपनी स्क्रिप्ट के अंदर, किसी iterableफ़ंक्शन को परिभाषित करने के लिए सुविधाजनक पाता हूं । (अब एल्फ के सुझाए सरलीकरण को शामिल करता है):

import collections

def iterable(obj):
    return isinstance(obj, collections.Iterable):

इसलिए आप परीक्षण कर सकते हैं कि क्या कोई वस्तु बहुत पठनीय रूप में पुनरावृत्त है

if iterable(obj):
    # act on iterable
else:
    # not iterable

जैसा कि आप के साथ करना होगाcallable फ़ंक्शन के हैं

संपादित करें: यदि आप सुन्न स्थापित हैं, तो आप बस कर सकते हैं: से numpy import iterable, जो कि बस कुछ ऐसा है

def iterable(obj):
    try: iter(obj)
    except: return False
    return True

यदि आपके पास सुन्नता नहीं है, तो आप बस इस कोड को लागू कर सकते हैं, या ऊपर वाला।


3
जब भी आप sth like if x: return True else: return False( xबूलियन होने के साथ ) करते हैं तो आप इसे इस रूप में लिख सकते हैं return x। आपके मामले में return isinstance(…)बिना किसी के if
एल्फ

चूंकि आप स्वीकार करते हैं कि अल्फ का समाधान बेहतर है, तो आपने अपना उत्तर केवल कहने के लिए संपादित क्यों नहीं किया? इसके बजाय, अब आपके पास अपने उत्तर में BOTH संस्करण हैं। अनावश्यक शब्दाडंबर। इसे ठीक करने के लिए एक संपादन सबमिट कर रहा है।
टूलमेकरसैट

2
आपको "TypeError" को "अपवाद: रिटर्न फाल्स" लाइन को पकड़ना चाहिए। सब कुछ पकड़ना एक बुरा पैटर्न है।
मारियस जमरो जूल

पता है कि। मैंने NumPy लाइब्रेरी से कोड के उस टुकड़े का अनुवाद किया, जो सामान्य अपवाद का उपयोग करता है।
fmonegaglia 13

सिर्फ इसलिए कि NumPy से एक कोड लिया गया है, इसका मतलब यह नहीं है कि यह अच्छा है ... पैटर्न या नहीं, हर चीज को पकड़ने का एकमात्र समय ऐसा होना चाहिए, यदि आप अपने प्रोग्राम के अंदर स्पष्ट रूप से त्रुटि को हैंडल कर रहे हैं।
Tcll

5

इसमें एक अंतर्निहित कार्य होता है:

from pandas.util.testing import isiterable

हालांकि यह सिर्फ यह है कि क्या __iter__वास्तव में दृश्यों और समान के बारे में परवाह है या नहीं।
ead

4

यह हमेशा मुझे परेशान करता है कि क्यों अजगर के पास है, callable(obj) -> boolलेकिन नहीं iterable(obj) -> bool...
निश्चित रूप से यह करना आसान हैhasattr(obj,'__call__') भले ही यह धीमा हो।

चूँकि हर दूसरे उत्तर के बारे में सलाह दी जाती है try/ except TypeError, जहाँ अपवादों के परीक्षण को आम तौर पर किसी भी भाषा के बीच बुरा व्यवहार माना जाता है, यहाँ पर iterable(obj) -> boolमुझे अधिक शौकीन और अक्सर उपयोग करने का एक कार्यान्वयन मिला है :

अजगर 2 की खातिर, मैं सिर्फ उस अतिरिक्त प्रदर्शन को बढ़ावा देने के लिए एक मेमने का उपयोग करूँगा ...
(अजगर 3 में यह कोई फर्क नहीं पड़ता कि आप फ़ंक्शन को परिभाषित करने के लिए क्या उपयोग करते हैं, defलगभग उसी गति से है lambda)

iterable = lambda obj: hasattr(obj,'__iter__') or hasattr(obj,'__getitem__')

ध्यान दें कि यह फ़ंक्शन ऑब्जेक्ट्स के लिए तेज़ी से निष्पादित करता है __iter__क्योंकि यह परीक्षण नहीं करता है __getitem__

अधिकांश पुनरावृत्त वस्तुओं को उस पर भरोसा करना चाहिए __iter__जहां विशेष-मामले वस्तुएं वापस गिरती हैं __getitem__, हालांकि या तो किसी वस्तु को पुनरावृत्त होने के लिए आवश्यक है।
(और चूंकि यह मानक है, यह C वस्तुओं को भी प्रभावित करता है)


वह वर्किंग कोड प्रदान नहीं करता है, अकेले अजगर प्रदर्शन के बारे में बात करते हैं ... हालांकि यह जवाब वास्तव में सुविधा के लिए था जैसे मैंने कई बार यहां देखा है।
Tcll

3
def is_iterable(x):
    try:
        0 in x
    except TypeError:
        return False
    else:
        return True

यह सभी प्रकार की चलने वाली वस्तुओं के लिए हां कहेगा, लेकिन यह पायथन 2 में तार नहीं कहेगा । (यही मैं उदाहरण के लिए चाहता हूं जब एक पुनरावर्ती कार्य एक स्ट्रिंग या तारों का एक कंटेनर ले सकता है। उस स्थिति में, माफी मांगने से ऑबफ्यूकोड हो सकता है, और पहले अनुमति पूछना बेहतर है।)

import numpy

class Yes:
    def __iter__(self):
        yield 1;
        yield 2;
        yield 3;

class No:
    pass

class Nope:
    def __iter__(self):
        return 'nonsense'

assert is_iterable(Yes())
assert is_iterable(range(3))
assert is_iterable((1,2,3))   # tuple
assert is_iterable([1,2,3])   # list
assert is_iterable({1,2,3})   # set
assert is_iterable({1:'one', 2:'two', 3:'three'})   # dictionary
assert is_iterable(numpy.array([1,2,3]))
assert is_iterable(bytearray("not really a string", 'utf-8'))

assert not is_iterable(No())
assert not is_iterable(Nope())
assert not is_iterable("string")
assert not is_iterable(42)
assert not is_iterable(True)
assert not is_iterable(None)

यहां कई अन्य रणनीतियां तार के लिए हां कहेंगी। यदि आप चाहते हैं तो उनका उपयोग करें।

import collections
import numpy

assert isinstance("string", collections.Iterable)
assert isinstance("string", collections.Sequence)
assert numpy.iterable("string")
assert iter("string")
assert hasattr("string", '__getitem__')

नोट: is_iterable () प्रकार के तार के लिए हाँ कहेंगे bytesऔर bytearray

  • bytesपायथन 3 में वस्तुएं चलने योग्य हैं True == is_iterable(b"string") == is_iterable("string".encode('utf-8'))। पायथन 2 में ऐसा कोई प्रकार नहीं है।
  • bytearray पायथन 2 और 3 में वस्तुएँ चलने योग्य हैं True == is_iterable(bytearray(b"abc"))

ओपी hasattr(x, '__iter__')दृष्टिकोण (कोई फर्क नहीं पड़ता कि क्या अजगर 3 में और कोई अजगर 2 में तार करने के लिए हाँ कहेंगे ''या b''या u'')। यह देखने के लिए @LuisMasuelli को धन्यवाद, यह आपको एक छोटी गाड़ी पर नीचे जाने देगा __iter__


2

सबसे आसान तरीका है, अजगर के बत्तख टाइपिंग का सम्मान करना , त्रुटि को पकड़ना है (पायथन को पूरी तरह से पता है कि वह वस्तु से क्या उम्मीद करता है कि वह एक पुनरावृत्ति बनने वाला है):

class A(object):
    def __getitem__(self, item):
        return something

class B(object):
    def __iter__(self):
        # Return a compliant iterator. Just an example
        return iter([])

class C(object):
    def __iter__(self):
        # Return crap
        return 1

class D(object): pass

def iterable(obj):
    try:
        iter(obj)
        return True
    except:
        return False

assert iterable(A())
assert iterable(B())
assert iterable(C())
assert not iterable(D())

नोट :

  1. यह अंतर अप्रासंगिक है कि क्या वस्तु चलने योग्य नहीं है, या एक छोटी गाड़ी __iter__लागू की गई है, यदि अपवाद प्रकार समान है: वैसे भी आप ऑब्जेक्ट को पुनरावृत्त करने में सक्षम नहीं होंगे।
  2. मुझे लगता है कि मैं आपकी चिंता को समझता हूं: callableएक चेक के रूप में कैसे मौजूद है अगर मैं भी अपनी वस्तु के लिए परिभाषित नहीं है , AttributeErrorतो उठाने के लिए बतख टाइपिंग पर भरोसा कर सकता है __call__, लेकिन यह चलने योग्य जाँच के लिए मामला नहीं है?

    मुझे उत्तर नहीं पता है, लेकिन आप या तो मेरे द्वारा दिए गए फ़ंक्शन (और अन्य उपयोगकर्ताओं) को लागू कर सकते हैं, या बस अपने कोड में अपवाद को पकड़ सकते हैं (उस हिस्से में आपका कार्यान्वयन मेरे द्वारा लिखे गए फ़ंक्शन की तरह होगा - बस सुनिश्चित करें कि आप अलग-थलग करें कोड के बाकी हिस्सों से पुनरावृति निर्माण ताकि आप अपवाद को पकड़ सकें और इसे दूसरे से अलग कर सकें TypeError


1

isiterableनिम्नलिखित कोड रिटर्न पर समारोह Trueअगर वस्तु iterable है। अगर यह चलने योग्य रिटर्न नहीं हैFalse

def isiterable(object_):
    return hasattr(type(object_), "__iter__")

उदाहरण

fruits = ("apple", "banana", "peach")
isiterable(fruits) # returns True

num = 345
isiterable(num) # returns False

isiterable(str) # returns False because str type is type class and it's not iterable.

hello = "hello dude !"
isiterable(hello) # returns True because as you know string objects are iterable

2
बहुत सारे विस्तृत उत्तर कई अपवोट के साथ हैं और आप एक अस्पष्ट उत्तर में फेंकते हैं ... meh
Nrzonline

कृपया नंगे कोड पोस्ट न करें। इसमें यह भी शामिल है कि यह क्या कर रहा है।
जोनाथन मी

1

__iter__विशेषता के लिए जाँच करने के बजाय , आप उस विशेषता की जाँच कर सकते हैं __len__, जिसे स्ट्रिंग्स सहित, हर पाइथन बिल्डर द्वारा लागू किया जाता है।

>>> hasattr(1, "__len__")
False
>>> hasattr(1.3, "__len__")
False
>>> hasattr("a", "__len__")
True
>>> hasattr([1,2,3], "__len__")
True
>>> hasattr({1,2}, "__len__")
True
>>> hasattr({"a":1}, "__len__")
True
>>> hasattr(("a", 1), "__len__")
True

कोई भी पुनरावृत्त वस्तुएं स्पष्ट कारणों से इसे लागू नहीं करेगी। हालांकि, यह उपयोगकर्ता-परिभाषित पुनरावृत्तियों को नहीं पकड़ता है जो इसे लागू नहीं करते हैं, न ही जनरेटर के भाव, जो इससे iterनिपट सकते हैं। हालाँकि, यह एक पंक्ति में किया जा सकता है, और orजनरेटर के लिए एक सरल अभिव्यक्ति जाँच को जोड़ने से यह समस्या ठीक हो जाएगी। (ध्यान दें कि लेखन type(my_generator_expression) == generatorएक फेंक देगा NameError। इसके बजाय इस उत्तर को देखें ।)

आप जनरेटर टाइप का उपयोग कर सकते हैं:

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True

--- utdemir द्वारा स्वीकृत उत्तर

(यह जाँच के लिए उपयोगी बनाता है कि क्या आप lenऑब्जेक्ट पर कॉल कर सकते हैं ।)


दुर्भाग्य से सभी उपयोग करने योग्य वस्तुएं नहीं __len__... इस मामले के लिए, यह आमतौर पर 2 वस्तुओं के बीच की दूरी की गणना का अनुचित उपयोग है। जहाँ obj.dist()आसानी से प्रतिस्थापित किया जा सकता है।
टीसीएल

हाँ। अधिकांश उपयोगकर्ता परिभाषित iterables iter और getitem को लागू करते हैं लेकिन लेन नहीं। हालाँकि, निर्मित प्रकार में करते हैं, और यदि आप जाँचना चाहते हैं कि क्या आप इस पर लेन फ़ंक्शन कह सकते हैं, तो लेन की जाँच अधिक सुरक्षित है। लेकिन आप सही हैं।
डार्थकैडस

0

वास्तव में "सही" नहीं है, लेकिन स्ट्रिंग्स, टुपल्स, फ्लोट्स आदि जैसे अधिकांश सामान्य प्रकारों की त्वरित जांच के रूप में सेवा कर सकते हैं ...

>>> '__iter__' in dir('sds')
True
>>> '__iter__' in dir(56)
False
>>> '__iter__' in dir([5,6,9,8])
True
>>> '__iter__' in dir({'jh':'ff'})
True
>>> '__iter__' in dir({'jh'})
True
>>> '__iter__' in dir(56.9865)
False

0

किन्दा को पार्टी के लिए देर हो गई लेकिन मैंने खुद से यह सवाल पूछा और यह देखा फिर एक जवाब के बारे में सोचा। अगर किसी ने पहले से ही यह पोस्ट किया है मुझे नहीं पता। लेकिन अनिवार्य रूप से, मैंने देखा है कि सभी प्रकार के चलने योग्य प्रकारों में __getitem __ () होता है। यह है कि आप कैसे जाँचेंगे यदि कोई वस्तु बिना प्रयत्न के भी चलने योग्य थी। (जानबूझ का मजाक)

def is_attr(arg):
    return '__getitem__' in dir(arg)

दुर्भाग्य से, यह अविश्वसनीय है। उदाहरण
टाइमगैब

1
सेट ऑब्जेक्ट एक और प्रतिरूप हैं।
रेमंड हेटिंगर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.