4 python iterator tuples list python-3.x
我想建立一个只接受一个可迭代的参数,如方法list,tuple,set或dict.
这是我的代码:
class MjmMenuControl(MjmBaseMenu):
def __init__(self, items=None):
iterables = (dict, list, set, tuple)
for iterable in iterables:
if isinstance(items, iterable):
...
break
Run Code Online (Sandbox Code Playgroud)
但是,我想知道是否有更简单的方法,比如if isinstance(items, <iterable_base_class>):我找不到任何东西.
我已经尝试过为list等等找到基类但它们似乎都来自object:
>>> inspect.getmro(list)
(<class 'list'>, <class 'object'>)
>>> inspect.getmro(tuple)
(<class 'tuple'>, <class 'object'>)
Run Code Online (Sandbox Code Playgroud)
这是可能的还是我必须坚持可怕的for循环?
Mar*_*ers 14
是的,使用collections.abc.Iterable:
>>> from collections import abc
>>> isinstance(set(), abc.Iterable)
True
>>> isinstance((), abc.Iterable)
True
>>> isinstance([], abc.Iterable)
True
>>> isinstance('', abc.Iterable)
True
>>> isinstance({}, abc.Iterable)
True
>>> isinstance(0, abc.Iterable)
False
Run Code Online (Sandbox Code Playgroud)
但是,我只是假设它传递了一个可迭代的方法,调用者有责任确保传入正确的类型.
该collections.abc模块是Python 3.3中的新增功能; 它的内容以前只存在于collections模块中,尽管即使在Python 3.3及更高版本中,名称仍然可以在旧位置使用.
该collections.abc.Iterable选项的一个弱点是它无法处理这样的自定义可迭代类......
from collections.abc import Iterable
class MyIterable(object):
def __getitem__(self, index):
if index >= 10:
raise IndexError
return index
>>> myiter = MyIterable()
>>> isinstance(myiter, Iterable)
False
>>> [i for i in myiter]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
人们经常声称这样做的“Pythonic”方式是使用鸭子类型,即尝试将对象视为可迭代对象,并在失败时处理异常。例如...
class MjmMenuControl(MjmBaseMenu):
def __init__(self, items=None):
try:
for item in items:
do_something_with(item)
except TypeError:
# If we get here, 'items' is not iterable
do_something_else()
Run Code Online (Sandbox Code Playgroud)
...然而,这两种方法都有一个弱点,即将字符串视为与列表相同的东西,这通常不是您想要的。通常你想测试一个可迭代的容器,它略有不同,所以经常看到将字符串视为这样的特殊情况的代码......
class MjmMenuControl(MjmBaseMenu):
def __init__(self, items=None):
if isinstance(items, (str, bytes)):
do_something_else()
else:
try:
for item in items:
do_something_with(item)
except TypeError:
# If we get here, 'items' is not iterable
do_something_else()
Run Code Online (Sandbox Code Playgroud)
...这有点乱,但可以完成工作。