कैसे जांच करें कि क्या कोई वस्तु अजगर में एक जनरेटर वस्तु है?


157

अजगर में, मैं कैसे जांचूं कि कोई वस्तु एक जनरेटर वस्तु है?

यह कोशिश कर रहा है -

>>> type(myobject, generator)

त्रुटि देता है -

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'generator' is not defined

(मुझे पता है कि मैं जांच कर सकता हूं कि क्या वस्तु के पास nextजनरेटर के लिए एक विधि है, लेकिन मैं कुछ ऐसा तरीका चाहता हूं जिसके उपयोग से मैं किसी भी वस्तु का प्रकार निर्धारित कर सकता हूं, न कि केवल जनरेटर।)


4
आप किस वास्तविक समस्या को हल करने की कोशिश कर रहे हैं? अधिक संदर्भ पोस्ट करें, एक स्मार्ट तरीका हो सकता है। आपको यह जानने की आवश्यकता है कि क्या यह जनरेटर है?
डेनिथ

7
from types import GeneratorType;type(myobject, GeneratorType)आपको कक्षा 'जनरेटर' की वस्तुओं के लिए उचित परिणाम देगा। लेकिन जैसा कि डेनिथ का तात्पर्य है, यह जरूरी नहीं कि सही रास्ता है।
JAB

7
यदि आप जांच कर रहे हैं __next__, तो आप वास्तव में किसी भी इटिटर को स्वीकार कर रहे हैं, न कि केवल जनरेटर - जो बहुत ही संभव है कि आप क्या चाहते हैं।

2
जैसा कि अक्सर नहीं होता है, यह जानने का असली बिंदु कि क्या कुछ जनरेटर है, एक ही संग्रह में कई बार पुनरावृति के इच्छुक होने के कारण, उनसे बचने में सक्षम होना चाहिए।
इयान

2
उपयोग के मामले के बारे में सोच रहे लोगों के लिए, यह तब उपयोगी हो सकता है जब आपको यह जानने की आवश्यकता हो कि क्या इटरेटर का सेवन किया जाएगा (जैसे कि यदि आपका फ़ंक्शन किसी भी पुनरावृत्त को स्वीकार करता है, लेकिन एक से अधिक बार पुनरावृति करने की आवश्यकता है, तो आप इसे पुनरावृत्त करने से पहले भौतिक बनाना चाहेंगे)
wadart

जवाबों:


227

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

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

5
यह दुर्भाग्य से जनरेटर कक्षाओं (उदाहरण के लिए, मानचित्र या फ़िल्टर ऑब्जेक्ट) के लिए काम नहीं करता है।
रिकार्डो क्रूज़

शायद isinstance(gen, (types.GeneratorType, map, filter))यह भी पता लगाने के लिए उपयोगी है mapऔर filter। यह अभी भी अन्य पुनरावृत्तियों और पुनरावृत्तियों को शामिल नहीं करेगा, हालांकि।
jlh

38

आप जनरेटर कार्यों का मतलब है? उपयोग करें inspect.isgeneratorfunction

संपादित करें:

यदि आप एक जेनरेटर ऑब्जेक्ट चाहते हैं, तो आप जेबीबी द्वारा अपनी टिप्पणी में बताए अनुसार निरीक्षणकर्ता का उपयोग कर सकते हैं ।


1
जनरेटर फ़ंक्शन जनरेटर वस्तु नहीं है; देखिये @ utdemir का जवाब
Piotr Findeisen

5
@Potr: जिस स्थिति में आप उपयोग करते हैं inspect.isgenerator
JAB

@JAB, @Piotr: ओपी का क्या मतलब हो सकता है, की सभी संभावनाओं को संबोधित करने के लिए परिलक्षित, धन्यवाद JAB :)
मौड

1
नोट: यदि आप केवल इस परीक्षण की जरूरत है, तो आप का उपयोग करके एक छोटे से भूमि के ऊपर से बच सकते हैं @utdemir समाधान क्योंकि inspect.isgeneratorकरने के लिए केवल एक आशुलिपि है: isinstance(object, types.GeneratorType)
bufh

जनरेटर ऑब्जेक्ट और जनरेटर फ़ंक्शन के बीच अंतर के लिए @RobertLujo उत्तर देखें। stackoverflow.com/a/32380774/3595112
industryworker3595112

24

मुझे लगता है कि जनरेटर के कार्यों और जनरेटर (जनरेटर फ़ंक्शन के परिणाम) के बीच अंतर करना महत्वपूर्ण है :

>>> def generator_function():
...     yield 1
...     yield 2
...
>>> import inspect
>>> inspect.isgeneratorfunction(generator_function)
True

कॉल जनरेटर_फंक्शन सामान्य परिणाम नहीं देगा, यहां तक ​​कि यह फ़ंक्शन में किसी भी कोड को निष्पादित नहीं करेगा, परिणाम जनरेटर नामक विशेष ऑब्जेक्ट होगा :

>>> generator = generator_function()
>>> generator
<generator object generator_function at 0x10b3f2b90>

इसलिए यह जनरेटर फ़ंक्शन नहीं है, लेकिन जनरेटर:

>>> inspect.isgeneratorfunction(generator)
False

>>> import types
>>> isinstance(generator, types.GeneratorType)
True

और जनरेटर फ़ंक्शन जनरेटर नहीं है:

>>> isinstance(generator_function, types.GeneratorType)
False

सिर्फ एक संदर्भ के लिए, फंक्शन बॉडी की वास्तविक कॉल जनरेटर का उपभोग करने से होगी, जैसे:

>>> list(generator)
[1, 2]

यह भी देखें कि अजगर में यह जांचने का एक तरीका है कि क्या कॉल करने से पहले कोई फ़ंक्शन "जनरेटर फ़ंक्शन" है?


11

inspect.isgeneratorसमारोह ठीक आप शुद्ध जनरेटर (यानी वर्ग "जनरेटर" की वस्तुओं) के लिए जाँच करने के लिए चाहते हैं। हालाँकि False, यदि आप जाँच करते हैं, तो यह वापस आ जाएगा , उदाहरण के लिए, एक izipचलने योग्य। एक सामान्यीकृत जनरेटर के लिए जाँच का एक वैकल्पिक तरीका इस फ़ंक्शन का उपयोग करना है:

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')

1
हम्म। इसके लिए सही रिटर्न x=iter([1,2])। मुझे लगता है यह वास्तव में परीक्षण है या नहीं, एक वस्तु एक है इटरेटर , नहीं एक जनरेटर। लेकिन हो सकता है कि "पुनरावृत्ति" ठीक वही है जो आप "सामान्यीकृत जनरेटर" से मतलब रखते हैं।
जोश ओ'ब्रायन

3

आप Iterator या विशेष रूप से, टाइपिंग मॉड्यूल से जनरेटर का उपयोग कर सकते हैं ।

from typing import Generator, Iterator
g = (i for i in range(1_000_000))
print(type(g))
print(isinstance(g, Generator))
print(isinstance(g, Iterator))

परिणाम:

<class 'generator'>
True
True

1
एक काम के समाधान के लिए +1। यह कहा जा रहा है, typing.TypeVarवर्ग के लिए डॉक्स मॉड्यूल isinstanceके साथ संयोजन के उपयोग को हतोत्साहित करते हैं typing: " सामान्य तौर पर, isinstance(x, T)उठाएंगे TypeError। सामान्य तौर पर, isinstance()और issubclass()प्रकारों के साथ उपयोग नहीं किया जाना चाहिए।"
जशा

2
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True

यह केवल तभी काम करता है जब यह एक फ़ंक्शन है। यदि 'फू' एक जेनरेटर ऑब्जेक्ट है, तो यह 'गलत' दिखाता है। मेरा प्रश्न देखें, मैं जनरेटर वस्तुओं के लिए जाँच करना चाहता हूँ।
पुष्पक डगड़े

2

मुझे पता है कि मैं यह जांच सकता हूं कि क्या वस्तु के पास जनरेटर के लिए एक अगली विधि है, लेकिन मैं कुछ ऐसा तरीका चाहता हूं जिसके उपयोग से मैं किसी भी वस्तु का प्रकार निर्धारित कर सकता हूं, न कि केवल जनरेटर।

यह मत करो। यह बस एक बहुत बुरा विचार है।

इसके बजाय, यह करें:

try:
    # Attempt to see if you have an iterable object.
    for i in some_thing_which_may_be_a_generator:
        # The real work on `i`
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else

अप्रत्याशित घटना है कि के शरीर में के लिए पाश भी है TypeError(1) त्रुटियों की गुंजाइश, या (2) एक नेस्टेड का उपयोग को सीमित करने के एक समारोह को परिभाषित: रों, वहाँ कई विकल्प हैं कोशिश ब्लॉक।

या (3) कुछ इस तरह से इन सभी को अलग करने के लिए TypeErrorजो चारों ओर तैर रहे हैं।

try:
    # Attempt to see if you have an iterable object.
    # In the case of a generator or iterator iter simply 
    # returns the value it was passed.
    iterator = iter(some_thing_which_may_be_a_generator)
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else
else:
    for i in iterator:
         # the real work on `i`

या (4) अपने एप्लिकेशन के अन्य हिस्सों को जनरेटर को उचित रूप से प्रदान करने के लिए ठीक करें। यह अक्सर इस सब से सरल है।


1
आपका समाधान लूप के लिए बॉडी द्वारा फेंके गए टाइपर्र को पकड़ लेगा। मैंने एक संपादन का प्रस्ताव किया है जो इस अवांछनीय व्यवहार को रोक देगा।
टिब्बा

यह गलत तरीके से करने का अधिक पायथोनिक तरीका है, अगर मैं गलत नहीं हूं।
JAB

हालाँकि, यदि आप आइटम्स की सूची से अधिक पुनरावृति कर रहे हैं और उनमें से अधिक पुनरावृत्तियाँ पुनरावृत्तियों की तुलना में नहीं हैं, तो यह निश्चित रूप से हो सकता है?
जैकब बोयर

1
@ जाकोब बोयर: अपवाद ifबयानों से तेज हैं । तथा। इस तरह का सूक्ष्म अनुकूलन समय की बर्बादी है। एल्गोरिदम को ठीक करें जो केवल पुनरावृत्तियों का उत्पादन करने के लिए पुनरावृत्तियों और गैर-पुनरावृत्तियों के मिश्रित बैग का उत्पादन करता है और अपने आप को इस दर्द से बचा सकता है।
S.Lott

10
यह एक जनरेटर के रूप में किसी भी पुनरावृत्ति को गलती से मान लेगा।
बाल्की

1

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

def chainPool(*arg):
    for f in arg:
      if(hasattr(f,"__iter__")):
          for e in f:
             yield e
      else:
         yield f

अब जंजीर जनरेटर जैसे लेखन

[x for x in chainPool(chainPool(1,2),3,4,chainPool(5,chainPool(6)))]

उत्पादन करता है

[1, 2, 3, 4, 5, 6]

अगर आप जेनरेटरों को थ्रेड विकल्प या समान के रूप में उपयोग करना चाहते हैं, तो आप शायद यही चाहते हैं।


1

(मुझे पता है कि यह एक पुरानी पोस्ट है।) मॉड्यूल आयात करने की कोई आवश्यकता नहीं है, आप कार्यक्रम की शुरुआत में तुलना के लिए एक वस्तु की घोषणा कर सकते हैं:

gentyp= type(1 for i in "")                                                                                          
       ...
type(myobject) == gentyp
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.