首页 > Python > Python类型检查方法

Python类型检查方法

上一篇 下一篇

有没有像这样的方法?到目前为止,我找到的唯一解决方案是致电isiterable

hasattr(myObj, '__iter__')

但我不确定这有多万无一失。

分割线

网友回答:

鸭子打字

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

# for obj in iterator:
#     pass

类型检查

使用抽象基类。它们至少需要 Python 2.6,并且仅适用于新式类。

from collections.abc import Iterable   # import directly from collections for Python < 3.3

if isinstance(the_element, Iterable):
    # iterable
else:
    # not iterable

但是,如文档所述,更可靠一些:iter()

选中会检测注册为
可迭代或具有方法的类,但
不会检测使用
该方法迭代的类。确定对象
是否可迭代的唯一可靠方法是调用 。
isinstance(obj, Iterable)__iter__()__getitem__()iter(obj)

分割线

网友回答:

  1. 检查适用于序列类型,但在 Python 2 中的字符串上会失败。我也想知道正确的答案,在那之前,这里有一种可能性(也适用于字符串):__iter__
     try:
         some_object_iterator = iter(some_object)
     except TypeError as te:
         print(some_object, 'is not iterable')
    

内置检查方法,如果是字符串,则检查方法。iter__iter____getitem__

  1. 另一种通用的pythonic方法是假设一个可迭代对象,如果它在给定对象上不起作用,则优雅地失败。Python 词汇表:

一种 pythonic 编程风格,通过检查对象的方法或属性签名来确定对象的类型,而不是通过与某个类型对象的显式关系来确定对象(“如果它看起来像子,嘎嘎叫像鸭子,它一定是鸭子。通过强调接口而不是特定类型,设计良好的代码通过允许多态替换来提高其灵活性。鸭子类型避免使用 type() 或 isinstance() 进行测试。相反,它通常采用EAFP(比许可更容易请求宽恕)风格的编程。

try:
   _ = (e for e in my_object)
except TypeError:
   print my_object, 'is not iterable'
  1. 该模块提供了一些抽象基类,这些基类允许询问类或实例是否提供特定功能,例如:collections
     from collections.abc import Iterable
    
     if isinstance(e, Iterable):
         # e is iterable
    

但是,这不会检查可通过 迭代的类。__getitem__

分割线

网友回答:

我想更多地阐明 的相互作用,以及幕后发生的事情。有了这些知识,您将能够理解为什么您能做的最好的事情是iter__iter____getitem__

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

我将首先列出事实,然后快速提醒您在python中使用循环时会发生什么,然后进行讨论以说明事实。for

事实

  1. 如果至少满足以下条件之一,则可以通过调用从任何对象获取迭代器:oiter(o)a) 有一个返回迭代器对象的方法。迭代器是具有 and a (Python 2: ) 方法的任何对象。o__iter____iter____next__next

    b)有一个方法。o__getitem__

  2. 检查 或 的实例或检查
    属性是不够的。
    IterableSequence__iter__
  3. 如果一个对象只实现 ,而不实现,将构造
    一个迭代器,该迭代器尝试从整数索引中获取项目,从索引 0 开始。迭代器将捕获引发的任何(但没有其他错误),然后引发自身。
    o__getitem____iter__iter(o)oIndexErrorStopIteration
  4. 在最一般的意义上,除了尝试之外,没有办法检查返回的迭代器是否正常。iter
  5. 如果一个对象实现,该函数将确保
    返回的对象是一个迭代器。如果对象仅实现 ,则没有健全性检查
    o__iter__iter__iter____getitem__
  6. __iter__赢了。如果对象同时实现 和 ,将调用 。o__iter____getitem__iter(o)__iter__
  7. 如果要使自己的对象可迭代,请始终实现该方法。__iter__

for循环

为了跟上进度,你需要了解在Python中使用循环时会发生什么。如果您已经知道,请随时直接跳到下一部分。for

当你使用一些可迭代的对象时,Python调用并期望一个迭代器对象作为返回值。迭代器是实现(或在 Python 2 中)方法和方法的任何对象。for item in ooiter(o)__next__next__iter__

按照惯例,迭代器的方法应该返回对象本身(即 )。然后 Python 调用迭代器,直到被引发。所有这些都隐式发生,但以下演示使其可见:__iter__return selfnextStopIteration

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

使用 的实例调用将返回一个迭代器,没有任何问题,因为实现 .iterBasicIterableBasicIterable__getitem__

>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>

但是,重要的是要注意,它没有该属性,并且不被视为 或 的实例:b__iter__IterableSequence

>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False

这就是为什么Luciano Ramalho的Fluent Python建议调用和处理潜力作为检查对象是否可迭代的最准确方法。直接引用书中的话:iterTypeError

从 Python 3.4 开始,检查对象是否可迭代的最准确方法是调用并处理异常(如果不是)。这比使用 更准确,因为也会考虑传统方法,而 ABC 则不考虑。xiter(x)TypeErrorisinstance(x, abc.Iterable)iter(x)__getitem__Iterable

在第 3 点:迭代仅提供__getitem__但不提供__iter__的对象

遍历 的实例按预期工作:Python
构造一个迭代器,该迭代器尝试按索引获取项目,从零开始,直到引发 an。演示对象的方法仅返回由 返回的迭代器作为参数提供的 。
BasicIterableIndexError__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

请注意,迭代器在无法返回下一项时引发,并且引发的 for 在内部处理。这就是为什么循环使用 a 按预期工作的原因:StopIterationIndexErroritem == 3BasicIterablefor

>>> for x in b:
...     print(x)
...
0
1
2

下面是另一个示例,以便说明迭代器如何尝试按索引访问项目的概念。 不继承自 ,这意味着实例没有方法。iterWrappedDictdict__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

请注意,调用 to 是委托给的,方括号表示法只是一种简写。__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__

当为对象调用 时,将确保 的返回值 ,如果该方法存在,则是一个迭代器。这意味着返回的对象
必须实现(或在 Python 2 中)和 . 不能对仅
提供 的对象执行任何健全性检查,因为它无法检查对象的项目是否可通过整数索引访问。
iter(o)oiter__iter____next__next__iter__iter__getitem__

class FailIterIterable(object):
    def __iter__(self):
        return object() # not an iterator

class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception

请注意,从实例构造迭代器会立即失败,而从实例构造迭代器会成功,但在第一次调用 时会引发异常。FailIterIterableFailGetItemIterable__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

第6点:__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

关于第 7 点:您的可迭代类应该实现__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__iterTypeError
  3. 存在的特殊处理是出于向后兼容性的原因。再次引用Fluent Python:__getitem__

这就是为什么任何 Python 序列都是可迭代的:它们都实现了 .事实上,标准序列也实现了 ,你的也应该实现,
因为
出于向后兼容性的原因存在的特殊处理,并且将来可能会
消失(尽管在我写这篇文章时它没有被弃用)。
__getitem____iter____getitem__

模板简介:该模板名称为【Python类型检查方法】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 289次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 03-08
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
微信素材 html5 微信文章 企业网站 自适应 微信模板 单页式简历模板 微信公众平台 微信图片 响应式
您可能会喜欢的其他模板