পাইথনে কোনও বস্তু জেনারেটর বস্তু কিনা তা কীভাবে পরীক্ষা করবেন?


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)ক্লাস 'জেনারেটর' এর বস্তুর জন্য আপনাকে যথাযথ ফলাফল দেবে। তবে দেনিথ ইঙ্গিত হিসাবে, এটি অবশ্যই যাওয়ার সঠিক উপায় নয়।
জাব

7
আপনি যদি যাচাই করে থাকেন __next__, আপনি আসলে কোনও জেনারেটর নয়, কোনও পুনরুদ্ধারকারীকে গ্রহণ করছেন - যা আপনি চান তা সম্ভবত।

2
প্রায়শই না, একই সংগ্রহটি একাধিকবার পুনরাবৃত্তি করার ইচ্ছার কারণে কোনও কিছু জেনারেটর কিনা তা জানার আসল পয়েন্টটি সেগুলি এড়াতে সক্ষম হয়।
আয়ান

2
লোকেদের ব্যবহারের ক্ষেত্রে ভাবছেন, এটি কার্যকর হতে পারে যখন আপনার যখন পুনরুক্তি গ্রহণ করা হবে কিনা তা জানতে হবে (যেমন যদি আপনার ফাংশনটি কোনও পুনরুক্তি গ্রহণ করে তবে একাধিকবার পুনরাবৃত্তি করা দরকার, আপনি পুনরাবৃত্ত হওয়ার আগে এটি বাস্তবায়ন করতে চান)
wbadart

উত্তর:


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
জেনারেটর ফাংশন জেনারেটর অবজেক্ট নয়; @ উড্ডেমিরের উত্তর দেখুন
পাইোটার ফাইন্ডেন

5
@ পাইওটার: যে ক্ষেত্রে আপনি ব্যবহার করেন inspect.isgenerator
জাব

@ জ্যাব, @ পাইওটর: ওপি বলতে কী বোঝাতে পারে তার সমস্ত সম্ভাবনা সম্বোধন করতে প্রতিফলিত হয়েছে, ধন্যবাদ জ্যাব :)
মোঃ

1
নোট: আপনি শুধুমাত্র এই পরীক্ষাটি, আপনি ব্যবহার করে একটি ছোট ওভারহেড এড়াতে পারেন @utdemir সমাধান কারণ inspect.isgeneratorআপনি কেবল সাধারণভাবে সংক্ষেপে হল: isinstance(object, types.GeneratorType)
বুফ

জেনারেটর অবজেক্ট এবং জেনারেটর ফাংশনের মধ্যে পার্থক্যের জন্য @ রবার্টলুজো উত্তর দেখুন। stackoverflow.com/a/32380774/3595112
শিল্পকর্ম

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)উত্থাপিত হবে TypeErrorIn সাধারণভাবে, isinstance()এবং issubclass()প্রকারের সাথে ব্যবহার করা উচিত নয়।"
জশা

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

এটি কেবলমাত্র যদি কোনও ফাংশন হয় তবে এটি কাজ করে। যদি 'foo' একটি জেনারেটর অবজেক্ট হয় তবে এটি 'মিথ্যা' দেখায়। আমার প্রশ্নটি দেখুন, আমি জেনারেটরের জিনিসগুলির জন্য চেক তৈরি করতে চাই।
পুষ্প দাগাদে

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) একটি নেস্টেড ব্যবহার সীমিত করতে একটি ফাংশন নির্ধারণ: S, বহু পছন্দ করে দেখুন ব্লক।

বা (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
আপনার দ্রবণটি লুপের শরীরের দ্বারা ছুঁড়ে দেওয়া প্রকারভেদগুলি ধরবে। আমি একটি সম্পাদনা প্রস্তাব করেছি যা এই অনাকাঙ্ক্ষিত আচরণকে আটকাতে পারে।
ডিউনেস

যদি আমি ভুল না হয়ে থাকি তবে এটি করার আরও বেশি পাইথোনিক উপায়।
জ্যাব

যদিও, আপনি যদি আইটেমগুলির একটি তালিকা ধরে পুনরাবৃত্তি করছেন এবং তাদের মধ্যে অনেকগুলি পুনরাবৃত্তকারীগুলির চেয়ে পুনরাবৃত্তি না হয় তবে এটি অবশ্যই বেশি সময় নিতে পারে?
জাকব বোয়ার

1
@ জ্যাকব বাউয়ার: ব্যতিক্রমী ifবিবৃতিগুলির চেয়ে দ্রুত । এবং. এই ধরণের মাইক্রো-অপ্টিমাইজেশন সময় অপচয় করা। কেবল পুনরাবৃত্তর উত্পাদন করতে এবং নিজেকে এই সমস্ত ব্যথা বাঁচাতে পুনরাবৃত্তকারী এবং অ-পুনরাবৃত্তকারীগুলির একটি মিশ্র ব্যাগ তৈরি করে এমন অ্যালগরিদম ঠিক করুন।
এসলট

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.