Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python iterables的通用基类?_Python_List_Python 3.x_Iterator_Tuples - Fatal编程技术网

Python iterables的通用基类?

Python iterables的通用基类?,python,list,python-3.x,iterator,tuples,Python,List,Python 3.x,Iterator,Tuples,我正在尝试创建一个只接受iterable参数的方法,例如列表,元组,集或dict 这是我的密码: class MjmMenuControl(MjmBaseMenu): def __init__(self, items=None): iterables = (dict, list, set, tuple) for iterable in iterables: if isinstance(items, iterable):

我正在尝试创建一个只接受iterable参数的方法,例如
列表
元组
dict

这是我的密码:

class MjmMenuControl(MjmBaseMenu):
    def __init__(self, items=None):
        iterables = (dict, list, set, tuple)
        for iterable in iterables:
            if isinstance(items, iterable):
                ...
                break
但是,我想知道是否有更简单的方法,例如
如果是instance(items,):
但我什么也找不到

我已经尝试为
列表
等查找基类,但它们似乎都来自
对象

>>> inspect.getmro(list)
(<class 'list'>, <class 'object'>)
>>> inspect.getmro(tuple)
(<class 'tuple'>, <class 'object'>)
>inspect.getmro(列表)
(, )
>>>inspect.getmro(元组)
(, )
这是可能的还是我必须坚持使用可怕的
for
循环?

是的,使用:

但是,我会让方法假设它传递了一个iterable,调用者有责任确保传递了正确的类型


在Python3.3中是新的;它的内容以前存在于中,尽管名称即使在Python3.3及更高版本中仍在旧位置可用。

collections.abc.Iterable选项的一个缺点是它无法处理像这样的自定义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]
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()
经常有人声称,实现这一点的“Pythonic”方法是使用,即尝试将对象视为一个iterable,并在其失败时处理异常。例如

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()
…但是,这两种方法都有一个缺点,就是将字符串视为与列表相同的东西,而列表通常不是您想要的。通常,您需要测试一个iterable容器,它与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]
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()

…这有点混乱,但完成了任务。

非常感谢,我会尽快接受:)您能解释一下为什么它没有显示在
inspect.getmro()
中吗,我以为它显示了所有基类?此外,该方法接受任何类型的参数,但对不同的类型执行不同的操作,因此这就是我需要检查其是否可编辑的真正原因。我想举一个例子,让我的程序只接受一个iterable会更容易理解:)
list
tuple
在这里不是子类,它们只是碰巧实现相同协议的不同类型。没有iterable基类。如果需要改变行为,那么测试
iterable
是一个不错的选择,是的。@qarma:我注意到Python 3文档中的状态最初是
集合的一部分;Python 3版本也有别名。@Dan:如果需要单独处理字符串,当然可以。或者
isinstance(foo,abc.Iterable)而不是isinstance(foo,str)
,等等。这取决于你想做什么,真的。“如果有更简单的方法”-是的,完全省略类型检查。顺便说一句,你实际上不需要
for
循环,
isinstance
可以将元组作为第二个参数,这样,如果第一个参数是元组中任何类的实例,它将返回
True
。@volatile Ahh感谢您的提示。:)自从问题被标记为python-3.x之后,我已经将
基串
改为
(str,bytes)
,在python-3.x中,它们不再有一个公共子类(除了
对象
)。你应该使用
\uuuuiter\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu iter\uuuuuuuuuuuuuuuuuuuuuuuuu。我记得在这一点上与蒂姆·彼得斯(Tim Peters)进行了长时间的争论。他一直强调Python不是关于“继承”,而是关于“接口”,因为它允许您编写对参数类型更宽容的函数。当时我不同意他的意见,但现在对我来说更有意义了否,
\uuuu getitem\uuuu
表示其他类型;例如,请参见
序列
ABC,但也可以参见
映射
ABC<代码>\uuuu getitem\uuuuuuuuuuuuuuuuuuu
支持旧式类型,而
\uuuuuuu iter\uuuuuuuuuuuuuuuuuuuuuuuuuu
是最新添加的,您的新代码确实应该使用它。我没有注意到
序列
可伸缩性
之间的细微区别,尽管它们有点相似。有可能OP真正想要的是前者,而不是后者。TBH,我大约在15年前开始使用Python,但我还没有时间跟上所有新特性。我将不得不进一步调查