পাইথনে, আমি কীভাবে নির্ধারণ করব যে কোনও বস্তু পুনরাবৃত্তিযোগ্য কিনা?


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)

উপরেরগুলি ইতিমধ্যে সুপারিশ করা হয়েছিল, তবে সাধারণ sensকমত্যটি ব্যবহার iter()করা আরও ভাল হবে:

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

আমরা iter()আমাদের কোডগুলিতেও এই উদ্দেশ্যে ব্যবহার করেছি, তবে আমি ইদানীং কেবল __getitem__পুনরাবৃত্ত বলে বিবেচিত সামগ্রীর দ্বারা আরও বেশি করে বিরক্ত হতে শুরু করেছি । __getitem__অ-পুনরাবৃত্তিযোগ্য অবজেক্টে থাকার বৈধ কারণ রয়েছে এবং তাদের সাথে উপরের কোডটি ভালভাবে কাজ করে না। বাস্তব জীবনের উদাহরণ হিসাবে আমরা ফেকারকে ব্যবহার করতে পারি । উপরের কোডটি এটি পুনরাবৃত্তিযোগ্য বলে প্রতিবেদন করে তবে প্রকৃতপক্ষে পুনরাবৃত্তি করার চেষ্টা করে এটি একটি কারণ হয়ে যায় AttributeError(ফেকার ৪.০.২ এর সাথে পরীক্ষিত):

>>> 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(), তবে আমরা দুর্ঘটনাক্রমে ফেকার দৃষ্টান্তগুলি (বা কেবলমাত্র অন্য কোনও __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... যে কোনও সময় আপনি কেবল কিছু পুনরাবৃত্তিযোগ্য কিনা তা দেখতে চান।
thorwhalen

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. আর একটি সাধারণ পাইথোনিক পদ্ধতির একটি পুনরাবৃত্তিযোগ্য অনুমান করা হয়, তবে যদি প্রদত্ত বস্তুর উপর এটি কাজ না করে তবে কৃত্রিমভাবে ব্যর্থ হন। পাইথন গ্লোসারি:

    Pythonic প্রোগ্রামিং শৈলী যে তার পদ্ধতি বা অ্যাট্রিবিউট স্বাক্ষর পরিদর্শন দ্বারা বদলে কিছু টাইপ বস্তু ( "এটি একটি মত দেখায় থাকলে স্পষ্ট সম্পর্ক দ্বারা একটি বস্তু ধরন নির্ধারণ করে হাঁস এবং একটি মত quacks হাঁস , এটি একটি হওয়া আবশ্যক হাঁস ।") জোর ইন্টারফেসগুলি দ্বারা নির্দিষ্ট ধরণের পরিবর্তে, সু-নকশিত কোডটি বহুমুখী প্রতিস্থাপনের অনুমতি দিয়ে তার নমনীয়তা উন্নত করে। হাঁস-টাইপিং টাইপ () বা ইসিনস্ট্যান্স () ব্যবহার করে পরীক্ষা এড়ায়। পরিবর্তে, এটি প্রোগ্রামিংয়ের স্টাইলটি সাধারণত EAFP (অনুমতি চেয়ে ক্ষমা চাওয়ার চেয়ে সহজ) নিয়োগ করে।

    ...

    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
যদি কোনও_বজেক্ট অন্য কারণে (বাগ ইত্যাদি) কারণে টাইপররও ফেলে দেয় তবে কী হবে? আমরা কীভাবে এটি "পুনরাবৃত্তযোগ্য টাইপআরার" থেকে বলতে পারি?
শং

54
দ্রষ্টব্য যে পাইথন 3 এ: hasattr(u"hello", '__iter__')প্রত্যাবর্তনTrue
কার্লোস

572

হাঁসের টাইপিং

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

# for obj in iterator:
#     pass

টাইপ চেকিং

বিমূর্ত বেস ক্লাস ব্যবহার করুন । তাদের কমপক্ষে পাইথন ২.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
লুসিয়ানো রামালহোর "ফ্লুয়েন্ট পাইথন" থেকে: পাইথন ৩.৪ হিসাবে, কোনও অবজেক্ট এক্সটি পুনরাবৃত্তিযোগ্য কিনা তা যাচাই করার সর্বাধিক সঠিক উপায়টি হ'ল ইটার (এক্স) কে কল করা এবং যদি টাইপআরর ব্যতিক্রম না হয় তবে এটি পরিচালনা করা। এটি isinstance (x, abc.Iterable) ব্যবহার করার চেয়ে আরও নির্ভুল, কারণ ইটার (এক্স) উত্তরাধিকারী গেটিটেম পদ্ধতিটিও বিবেচনা করে , অন্যদিকে আইটেমারেবল এবিসি না করে।
আরডিবি

যদি আপনি "ওহ আমি ঠিক 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
আইটেমের মাধ্যমে ইটার () কল করা একটি ব্যয়বহুল ক্রিয়াকলাপ হতে পারে (পাইটর্কের ডেটালয়েডার দেখুন, যা এটির ()) এ একাধিক প্রক্রিয়া কাঁটাচামচ করে / চালিত করে।
szali

125

আমি একটু পারস্পরিক উপর আরো হালকা বিট চালা চাই iter, __iter__এবং __getitem__কি পর্দা পিছনে ঘটবে। সেই জ্ঞান দিয়ে সজ্জিত, আপনি বুঝতে পারবেন যে আপনি সবচেয়ে ভাল করতে পারেন কেন

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

আমি প্রথমে তথ্যগুলি তালিকাভুক্ত করব এবং তারপরে অজগরটিতে কোনও forলুপ নিযুক্ত করি এবং তারপরে ঘটনাগুলি বর্ণনা করার জন্য একটি আলোচনার পরে কী ঘটে যায় তার দ্রুত অনুস্মারকটি অনুসরণ করব।

তথ্য

  1. নিম্নলিখিত শর্তগুলির মধ্যে কমপক্ষে কোনওটি সত্য বলে ধরে রাখলে আপনি oকল করে iter(o)যে কোনও অবজেক্ট থেকে একটি ইটারেটর পেতে পারেন :

    ক) oএমন একটি __iter__পদ্ধতি রয়েছে যা একটি পুনরাবৃত্তকারী অবজেক্টকে প্রদান করে। একটি পুনরাবৃত্তকারী হ'ল একটি __iter__এবং __next__পাইথন 2 next:) পদ্ধতিযুক্ত যেকোন বস্তু ।

    খ) oএকটি __getitem__পদ্ধতি আছে।

  2. এর Iterableউদাহরণ Sequenceবা জন্য অনুসন্ধান করা বা বৈশিষ্ট্যের __iter__জন্য অনুসন্ধান করা যথেষ্ট নয়।

  3. যদি কোনও অবজেক্ট oকেবল প্রয়োগ করে __getitem__, তবে তা নয় __iter__, iter(o)একটি পুনরুক্তি তৈরি করবে oযা সূচক 0 থেকে শুরু করে পূর্ণসংখ্য সূচক থেকে আইটেম আনার চেষ্টা করে The পুনরুক্তি IndexErrorকরা উত্থাপিত কোনও (তবে অন্য কোনও ত্রুটি) ধরা পড়বে এবং তারপরে StopIterationনিজেই উত্থাপিত হবে ।

  4. খুব সাধারণ অর্থে, iterএটির চেষ্টা করা ছাড়াও পুনরুক্তি করা ইটারেটরটি বুদ্ধিমান কিনা তা যাচাই করার উপায় নেই ।

  5. যদি কোনও অবজেক্ট oপ্রয়োগ করে __iter__তবে iterফাংশনটি নিশ্চিত করবে যে প্রত্যাবর্তিত বস্তুটি __iter__একটি পুনরাবৃত্তকারী। কোনও বস্তু কেবল প্রয়োগ করে কিনা সেখানে কোনও বিড়াল চেক নেই __getitem__

  6. __iter__ধিক্কার জানাই। একটি বস্তু যদি oকার্যকরী উভয় __iter__এবং __getitem__, iter(o)ডাকব __iter__

  7. আপনি যদি নিজের আইটেমগুলিকে পুনরাবৃত্ত করতে চান তবে সর্বদা __iter__পদ্ধতিটি প্রয়োগ করুন ।

for লুপ

পাশাপাশি অনুসরণ করতে, আপনি forপাইথনে কোনও লুপ নিযুক্ত করলে কী ঘটে তা বোঝার প্রয়োজন you আপনি যদি ইতিমধ্যে জেনে থাকেন তবে নিখরচায় পরবর্তী বিভাগে যেতে পারেন।

আপনি যখন for item in oকিছু পুনরাবৃত্তিযোগ্য অবজেক্টের জন্য ব্যবহার করেন o, পাইথন কল দেয় iter(o)এবং প্রত্যাবর্তনের মান হিসাবে কোনও পুনরাবৃত্ত বস্তুর প্রত্যাশা করে। একটি পুনরুক্তি হ'ল কোনও বস্তু যা একটি __next__(বা nextপাইথন 2 এ) পদ্ধতি এবং একটি __iter__পদ্ধতি প্রয়োগ করে ।

কনভেনশন দ্বারা, __iter__একটি পুনরাবৃত্তির পদ্ধতিটি নিজেই (return 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। বই থেকে সরাসরি উদ্ধৃতি:

পাইথন ৩.৪ অনুসারে, কোনও বস্তুর xপুনরাবৃত্তিযোগ্য কিনা তা যাচাই করার সর্বাধিক সঠিক উপায়টি যদি iter(x)কোনও TypeErrorব্যতিক্রম না হয় তবে কল করা এবং পরিচালনা করতে হবে। এটি ব্যবহারের চেয়ে আরও সঠিক isinstance(x, abc.Iterable), কারণ iter(x)এটি উত্তরাধিকার __getitem__পদ্ধতিটিও বিবেচনা করে , যদিও Iterableএবিসি তা করে না।

3 পয়েন্টে: কেবলমাত্র সরবরাহ করে এমন অবজেক্টগুলিতে আইট্রেট করা __getitem__but__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তা অভ্যন্তরীণভাবে পরিচালিত হয় ises এ কারণেই 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

Point দফায়: __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

Point দফায়: আপনার পুনরাবৃত্তিযোগ্য ক্লাসগুলি প্রয়োগ করা উচিত __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ব্লক এবং Falseexcept TypeErrorঅবরোধ করবেন?
অ্যালাঙ্কলভিটি

এটি একটি দুর্দান্ত উত্তর। আমি মনে করি এটি গাইটাইটেম প্রোটোকলের অদম্য ও দুর্ভাগ্যজনক প্রকৃতির হাইলাইট করে। এটি কখনও যুক্ত করা উচিত ছিল না।
নিল জি

31

এটি পর্যাপ্ত নয়: প্রত্যাবর্তিত বস্তুর __iter__অবশ্যই পুনরাবৃত্তি প্রোটোকল (অর্থাত্ nextপদ্ধতি) প্রয়োগ করতে হবে । ডকুমেন্টেশনে প্রাসঙ্গিক বিভাগটি দেখুন

পাইথনে, একটি ভাল অনুশীলন হ'ল "চেকিং" এর পরিবর্তে "চেষ্টা করে দেখুন"।


9
"হাঁসের টাইপিং" বিশ্বাস করি? :)
উইলিম

9
@ উইলিম: বা "ক্ষমা চেয়ে অনুমতি চেয়ে বলবেন না" ;-)
jldupont

14
@ উইলিম "অনুমতি" এবং "ক্ষমা" উভয় শৈলী হাঁসের টাইপিংয়ের যোগ্যতা অর্জন করে। কি আপনি একটি বস্তু করতে জিজ্ঞাসা না বরং তা চেয়ে হয় , যে এর হাঁস টাইপিং। আপনি যদি আত্মতন্ত্র ব্যবহার করেন তবে এটি "অনুমতি"; যদি আপনি কেবল এটি করার চেষ্টা করেন এবং দেখুন এটি কার্যকর হয় কিনা, এটি "ক্ষমা"।
মার্ক রিড

22

পাইথন <= 2.5 এ, আপনি পারবেন না এবং করা উচিত নয় - পুনরাবৃত্তিযোগ্য একটি "অনানুষ্ঠানিক" ইন্টারফেস ছিল।

তবে পাইথন ২.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)

এখন, এটি পছন্দসই বা বাস্তবে কার্যকর কিনা তা কেবল সম্মেলনের বিষয়। আপনি দেখতে পারেন, আপনি পারেন একটি অ-পুনরাবৃত্তিযোগ্য অবজেক্টকে আইটেবল হিসাবে নিবন্ধভুক্ত - এবং এটি রানটাইমে একটি ব্যতিক্রম বাড়িয়ে তুলবে। সুতরাং, আইসনস্ট্যান্স একটি "নতুন" অর্থ অর্জন করে - এটি কেবল "ঘোষিত" ধরণের সামঞ্জস্যের জন্য পরীক্ষা করে, যা পাইথনে যাওয়ার জন্য একটি ভাল উপায়।

অন্যদিকে, যদি আপনার অবজেক্ট আপনার প্রয়োজনীয় ইন্টারফেসটি পূরণ না করে তবে আপনি কী করতে যাচ্ছেন? নিম্নলিখিত উদাহরণটি ধরুন:

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__ পদ্ধতিটি পাওয়া যায় তবে পাইথন স্বয়ংক্রিয়ভাবে class শ্রেণীর অবজেক্টকে Iteable হিসাবে স্বীকৃতি দেয়।

সুতরাং, আপনি যদি কেবল পুনরাবৃত্তিযোগ্য আশা করেন তবে এটির উপরে পুনরাবৃত্তি করুন এবং এটি ভুলে যান। অন্যদিকে, যদি আপনাকে ইনপুট ধরণের উপর নির্ভর করে বিভিন্ন জিনিস করার দরকার হয় তবে আপনি সম্ভবত এবিসি অবকাঠামোটিকে বেশ দরকারী বলে মনে করতে পারেন।


13
except:নতুনদের জন্য উদাহরণ কোডে খালি ব্যবহার করবেন না । এটি খারাপ অনুশীলনকে উত্সাহ দেয়।
jfs

জেএফএস: আমি করবো না, তবে একাধিক ব্যতিক্রম উত্থাপন কোডটি দিয়ে যাওয়ার দরকার ছিল এবং আমি নির্দিষ্ট ব্যতিক্রমটি ধরতে চাইনি ... আমি মনে করি এই কোডটির উদ্দেশ্যটি বেশ পরিষ্কার।
অ্যালান ফ্রানজোনি

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

আপনার হাঁসটি সত্যিই হাঁস কিনা তা দেখতে চেক চালাবেন না এটি পুনরাবৃত্তিযোগ্য কিনা তা দেখার জন্য, এটি যেমন ছিল তেমন আচরণ করুন এবং তা না হলে অভিযোগ করুন।


3
প্রযুক্তিগতভাবে, পুনরাবৃত্তির সময় আপনার গণনা একটি ফেলে দিতে পারে TypeErrorএবং আপনাকে এখানে ফেলে দিতে পারে তবে মূলত হ্যাঁ।
ক্রিস লুটজ

6
@ উইলেম: একটি মানদণ্ড সম্পাদন করতে দয়া করে টাইমিট ব্যবহার করুন। পাইথন ব্যতিক্রমগুলি প্রায়শই ইফ-স্টেটমেন্টের চেয়ে দ্রুত হয়। তারা দোভাষীর মাধ্যমে কিছুটা ছোট্ট পথ নিতে পারে।
এস .লট

2
@ উইলিম: আয়রন পাইথন ব্যতিক্রম ধীর (সিপাইনের তুলনায়) রয়েছে has
jfs

2
একটি কাজের চেষ্টা: বিবৃতিটি সত্যই দ্রুত। সুতরাং আপনার যদি কিছু ব্যাতিক্রম হয় তবে চেষ্টা-করা দ্রুত except আপনি যদি অনেকগুলি ব্যতিক্রম আশা করেন তবে "যদি" দ্রুত হতে পারে।
আরনে বাবেনহাউজারহিড

2
" as e" যোগ করার TypeErrorপরিবর্তে " " যোগ করে ব্যতিক্রম বস্তুটি ধরা উচিত নয় , e?
হ্যালো গুডবাই

21

যেহেতু পাইথন 3.5 আপনি ব্যবহার করতে পারেন টাইপিং জন্য টাইপ এর সাথে সম্পর্কিত কিছু মান লাইব্রেরি থেকে মডিউল:

from typing import Iterable

...

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

18

আমি এখনও অবধি সবচেয়ে ভাল সমাধানটি খুঁজে পেয়েছি:

hasattr(obj, '__contains__')

যা বস্তু inঅপারেটরটি প্রয়োগ করে তা মূলত যাচাই করে ।

সুবিধাগুলি (অন্য কোনও সমাধানের তিনটিতেই নেই):

  • এটি একটি অভিব্যক্তি ( ল্যাম্বডা হিসাবে কাজ করে , চেষ্টাটির বিপরীতে ... বৈকল্পিক ব্যতীত )
  • এটি (পুনরুদ্ধার করা উচিত) স্ট্রিং সহ সমস্ত পুনরাবৃত্ত দ্বারা প্রয়োগ করা উচিত (এর বিপরীতে __iter__)
  • যে কোনও পাইথন> = 2.5 এ কাজ করে

মন্তব্য:

  • "ক্ষমা প্রার্থনা করুন, অনুমতি নেই" এর পাইথন দর্শন ভাল কাজ করে না যখন উদাহরণস্বরূপ আপনার তালিকায় পুনরাবৃত্তিযোগ্য এবং অ-পুনরাবৃত্তিযোগ্য উভয়ই রয়েছে এবং আপনার প্রতিটি উপাদানকে তার ধরণ অনুসারে আলাদাভাবে আচরণ করা প্রয়োজন (চেষ্টা করুন এবং অ- ব্যতীত উপর iterables হায় কাজ তবে এটি বাট-কুৎসিত এবং বিভ্রান্তিকর দেখাবে)
  • এই সমস্যার সমাধান যা বস্তুর উপর প্রকৃতপক্ষে পুনরাবৃত্তি করার চেষ্টা করে (যেমন [অবজেক্টে এক্স এর জন্য এক্স]) এটি পুনরুক্তিযোগ্য কিনা তা বড় বড় পুনরাবৃত্তির জন্য গুরুত্বপূর্ণ পারফরম্যান্সের জরিমানা প্ররোচিত করতে পারে কিনা তা পরীক্ষা করার জন্য (বিশেষত যদি আপনাকে কেবল পুনরাবৃত্তের প্রথম কয়েকটি উপাদানগুলির প্রয়োজন হয় তবে) উদাহরণস্বরূপ) এবং এড়ানো উচিত

3
ভাল লাগছে, তবে স্ট্যাকওভারফ্লো / কোয়েশনস / ১৯৫৪৪৪৪/২ প্রস্তাবিত সংগ্রহের মডিউলটি কেন ব্যবহার করবেন না ? আমার কাছে আরও অভিব্যক্তি বলে মনে হচ্ছে।
ডেভ আব্রাহামস

1
কোনও স্বচ্ছতা ছাড়াই এটি সংক্ষিপ্ত (এবং অতিরিক্ত আমদানির প্রয়োজন হয় না): "অন্তর্ভুক্ত" পদ্ধতি থাকা কোনও বিষয়বস্তুর সংগ্রহ কিনা তা যাচাই করার প্রাকৃতিক উপায় বলে মনে হয়।
ভ্লাদ

46
যেহেতু কিছুতে কিছু থাকতে পারে তার অর্থ এটি পুনরুক্ত। উদাহরণস্বরূপ, কোনও ব্যবহারকারী কোনও পয়েন্টটি 3D কিউবে আছে কিনা তা পরীক্ষা করতে পারে তবে আপনি কীভাবে এই বস্তুর মাধ্যমে পুনরাবৃত্তি করবেন?
কেসি কুবাল

13
এটি ভুল। একটি পুনরাবৃত্ত নিজেই অন্তত পাইথন 3.4 সহ ধারণ করে না ।
পিটার শিনার্স 21:38

15

আপনি এটি চেষ্টা করতে পারেন:

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

যদি আমরা এমন একটি জেনারেটর তৈরি করতে পারি যা এটির উপরে পুনরাবৃত্তি করে (তবে জেনারেটরটি কখনই ব্যবহার না করে যাতে এটি স্থান নেয় না), এটি পুনরাবৃত্তিযোগ্য। "দুহ" ধরণের জিনিস বলে মনে হচ্ছে। ভেরিয়েবল প্রথম স্থানে পুনরাবৃত্তিযোগ্য কিনা তা আপনাকে কেন নির্ধারণ করতে হবে?


কি হবে iterable(itertools.repeat(0))? :)
Badp

5
@ এমডিপি, (x for x in a)খালি একটি জেনারেটর তৈরি করে , এটি কোনওটিতে কোনও পুনরাবৃত্তি করে না।
ক্যাচমেফিউট্রি

5
চেষ্টা করা (x for x in a)ঠিক কি সমান চেষ্টা iterator = iter(a)? বা কিছু ক্ষেত্রে আছে যেখানে দুটি পৃথক?
সর্বাধিক

for _ in a: breakআরও সোজা না ? এটা কি ধীর?
মিস্টার_আর_আমস_ডি

2
@ মিআর_আর_মরিস_ডি এটি খারাপ তবে যদি পরীক্ষিত বস্তুটি পুনরায় পুনরাবৃত্তি হয় তবে এটি পুনরায় পুনরুক্তি করা যায় না (এটি 1 আইটেম সংক্ষিপ্ত হবে কারণ তার অবস্থানটি পুনরায় সেট করা যায় না), আবর্জনা জেনারেটর তৈরি করে বস্তুর উপর পুনরাবৃত্তি হয় না কারণ তারা পুনরাবৃত্তি না করে, যদিও আমি নিশ্চিত নই যে এটি পুনর্বারযোগ্য না হলে 100% এটি টাইপরর বাড়িয়ে তুলবে।
Tcll

13

আমি একটা চমৎকার সমাধান পাওয়া এখানে :

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

10

পাইথন 2 গ্লোসারি অনুসারে , পুনরাবৃত্ত হয়

সব ক্রম ধরনের (যেমন list, strএবংtuple ) এবং মত কিছু অ ক্রম ধরনের dictএবং fileএবং কোন শ্রেণীর আপনি একটি সঙ্গে সংজ্ঞায়িত অবজেক্ট __iter__()বা __getitem__()পদ্ধতি। লুপের জন্য এবং অন্য অনেক স্থানে যেখানে সিকোয়েন্সের প্রয়োজন হয় (জিপ (), মানচিত্র (), ...) -তে Iteabless ব্যবহার করা যেতে পারে। যখন কোনও পুনরাবৃত্তিযোগ্য অবজেক্টটি অন্তর্নির্মিত ফাংশন ইটার () এর আর্গুমেন্ট হিসাবে পাস করা হয়, তখন এটি বস্তুর জন্য একটি পুনরাবৃত্তি প্রদান করে।

অবশ্যই, পাইথনের সাধারণ কোডিং শৈলীর ভিত্তিতে এটি "অনুমতিের চেয়ে ক্ষমা চাওয়া সহজ Eas" এর ভিত্তিতে সাধারণ প্রত্যাশাটি ব্যবহার করা হয়

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__")। আপনার উভয়ের জন্য পরীক্ষা করা দরকার, কারণ strs এর কোনও __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
আপনি যখনই বুথিয়ান if x: return True else: return False( xযেমন বুলিয়ান হওয়ার সাথে ) করেন তখন আপনি এটি লিখতে পারেন return x। আপনার ক্ষেত্রে return isinstance(…)কোনও ছাড়াই if
আলফে

যেহেতু আপনি স্বীকার করেছেন যে আলফের সমাধানটি আরও ভাল, তাই আপনি কেন নিজের উত্তরটি সম্পাদন করেননি কেবল তা বলার জন্য? পরিবর্তে, আপনার উত্তর এখন দুটি সংস্করণ আছে। অপ্রয়োজনীয় ভার্বোসিটি। এটি ঠিক করার জন্য একটি সম্পাদনা জমা দেওয়া হচ্ছে।
টুলমেকারস্টেভ

2
`বাদে: মিথ্যা se লাইনটি ফিরিয়ে নেওয়া উচিত Type সব কিছু ধরা খুব খারাপ প্যাটার্ন।
মারিউজ জামরো

জানি যে. আমি কোডটির এই অংশটি নুমপি লাইব্রেরি থেকে অনুবাদ করেছি, যা সাধারণ ব্যতিক্রম ব্যবহার করে।
fmonegaglia

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__, যদিও কোনও বস্তুর পুনরাবৃত্তিযোগ্য হওয়া আবশ্যক।
(এবং যেহেতু এটি প্রমিত, এটি সি বস্তুকেও প্রভাবিত করে)


তিনি ওয়ার্কিং কোড সরবরাহ করেন না, পাইথন পারফরম্যান্স সম্পর্কে একা কথা বলুন ... যদিও এই উত্তরটি কেবল সুবিধার জন্য ছিল যেমন আমি এখানে বহুবার দেখেছি।
টিসিএল

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

এটি সমস্ত পদ্ধতিতে পুনরাবৃত্তিযোগ্য অবজেক্টগুলিকে হ্যাঁ বলবে, তবে এটি পাইথন 2 তে স্ট্রিংগুলিকে না বলবে । (এটিই আমি উদাহরণস্বরূপ চাই যখন একটি পুনরাবৃত্ত ফাংশন স্ট্রিং বা স্ট্রিংয়ের ধারক নিতে পারে that সেই পরিস্থিতিতে ক্ষমা চাওয়ার ফলে অবফসকোড হতে পারে এবং প্রথমে অনুমতি চাইতে ভাল))

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-তে অবজেক্টগুলি পাইথন 2- True == is_iterable(b"string") == is_iterable("string".encode('utf-8'))তে কোনও ধরণের নেই।
  • bytearray পাইথন 2 এবং 3-তে অবজেক্টগুলি True == is_iterable(bytearray(b"abc"))

ওপি hasattr(x, '__iter__')পন্থা পাইথন 3 তে স্ট্রিংগুলিতে হ্যাঁ বলবে এবং পাইথন 2 তে কোনও হবে না (যাই হোক না কেন ''বা b''হোক u'')। এটি দেখার জন্য @ লুইসম্যাসুয়েলিকে ধন্যবাদ জানাই আপনাকে একটি বগিতে ফেলে দেবে __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__আমার বস্তুর জন্য সংজ্ঞায়িত করা হয় না, কিন্তু যে iterable পরীক্ষণের জন্য কেস নয়?

    আমি উত্তরটি জানি না, তবে আপনি আমার (এবং অন্যান্য ব্যবহারকারীগণ) প্রদত্ত ফাংশনটি বাস্তবায়ন করতে পারেন, বা কেবল আপনার কোডে ব্যতিক্রমটি ধরতে পারেন (সেই অংশে আপনার প্রয়োগটি আমি লিখেছি এমন ফাংশনের মতো হবে - কেবল নিশ্চিত করুন যে আপনি পৃথকীকরণকে বিচ্ছিন্ন করে দিন কোডটি বাকী থেকে পুনরুক্তি তৈরি করা যাতে আপনি ব্যতিক্রম ক্যাপচার করতে পারেন এবং এটি অন্যের থেকে আলাদা করতে পারেন TypeError


1

isiterableনিম্নলিখিত কোড আয় এ func 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
উপরে অনেক upvotes সহ উপরে অনেক বিস্তারিত উত্তর এবং আপনি একটি
অব্যক্ত

খালি কোড পোস্ট করবেন না দয়া করে। এটি কী করছে তার একটি ব্যাখ্যাও অন্তর্ভুক্ত করুন।
জোনাথন মে

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()সহজে প্রতিস্থাপন করা যেতে পারে।
Tcll

হ্যাঁ। বেশিরভাগ ব্যবহারকারীর সংজ্ঞায়িত পুনরাবৃত্তিগুলি ইটার এবং গেটাইটেম প্রয়োগ করে তবে লেন হয় না। যাইহোক, প্রকারভেদে তৈরি করা হয়, এবং যদি আপনি এটিতে লেন ফাংশনটি কল করতে পারেন কিনা তা পরীক্ষা করতে চান, লেনের জন্য চেক করা আরও সুরক্ষিত। তবে আপনি ঠিক বলেছেন।
দার্থকেডিয়াস

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