【问题标题】:__iter__: int and str vs list and tuple__iter__: int and str vs list and tuple
【发布时间】:2020-04-29 16:46:44
【问题描述】:
some_obj = "scalar"
list_like = "__iter__" in dir(some_obj)   # Py2: False; Py3: True

我在 python 2 中使用它来区分“不可迭代”(strintboolNone)和可迭代(listdicttuples)。

这不再适用于 python3,因为 str 现在具有 __iter__ 属性 (Why do strings in python 2.7 not have the "__iter__" attribute, but strings in python 3.7 have the "__iter__" attribute)。

嗯,通常希望将str 视为不像列表。那么有没有比"__iter__" in dir(some_obj) and not type(some_obj)==strthis question 中的所有案例检查更好的py2+py3 方式? 我会错过像str 这样有争议的其他对象吗?

【问题讨论】:

  • 任何实现__iter__ 的对象都通过了您的检查。你想用这个来完成什么?乍一看,这似乎不是一个好的做法,并且不清楚您将在哪里放置“可迭代”或“不可迭代”对象之间的边界。如果没有额外的背景,这个问题没有多大意义,它是基于意见/充其量是过于宽泛。
  • 由单个字符组成的列表和字符串有什么区别?在迭代方面什么都没有。 “内存中的紧凑对象”是一个相当空洞的标准。
  • @Friedrich 这正是我说这充其量是基于意见的原因。如果您想将“可迭代”定义为与语言定义不同的东西,那么请继续,但这实际上只是一种意见。
  • 嗯,一切都是比特的集合,最终在堆栈的某个地方。真正的问题是你想用它做什么,这可能会让我们更接近解决方案。在什么情况下你需要区分集合对象(我猜这就是你要问的?)和其他语言可能称之为“原始”的东西?
  • “通常希望将str 视为不像列表”。比如……什么时候? (不,我不把“我想用我的函数来区分容器和非容器”作为例子。这样的函数几乎总是写成容器更好,调用者可以写foo([x]),如果只有要传递的单个值。)

标签: python python-3.x python-2.7


【解决方案1】:

我不确定用__iter__检查类型好不好,这个有更好的选择,Iterable类型。

分组是你自己的意见,所以我认为最简单的方法是设置黑名单...

try:
    from collections.abc import Iterable # py3
except ImportError:
    from collections import Iterable #py2


def check(arg):
    if not isinstance(arg, Iterable):
        return False
    elif isinstance(arg, (str, bytes)):
        return False
    else:
        return True

【讨论】:

  • @deceze:如果您使用的是足够现代的 Python,我建议您将 bytes 替换为 collections.abc.ByteString;这将同时涵盖bytesbytearray 和其他类似bytes 的类型。假设您想要 bytes-like 类型被视为不可迭代;实际上,将它们视为可迭代的问题不大,因为与str 不同,它们是int 的可迭代对象,而不是str 的可迭代对象(这可能导致无限递归)。
【解决方案2】:

编辑: 为了不让我的回答引起混淆,我在这里引用了文档。

class collections.abc.Iterable

ABC 用于提供 iter() 方法的类。

检查 isinstance(obj, Iterable) 检测已注册的类 作为 Iterable 或具有 iter() 方法,但它没有检测到 使用 getitem() 方法迭代的类。唯一可靠的 判断一个对象是否可迭代的方法是调用iter(obj)

这适用于 2 和 3。 str当然是可迭代的。

n1 = 1
s1 = 'abc'

objs = [n1, s1]

for o in objs:
    try:
        iter(o)
    except TypeError:
        print(o, 'is not Iterable!')
    else:
        print(o, 'is Iterable!')

输出:

1 is not Iterable!
abc is Iterable!

引用来自here

【讨论】:

  • 而这正是 OP 想要避免的。
  • 我不认为提出我们自己的可迭代定义是一个好主意。 str 一个 Python 可迭代对象。或许你应该为我们自己的新类型想出一个抽象定义,然后注册 str ?
  • 另一个答案虽然部分不错,但也与官方文档相矛盾。
  • 这都是因为这个问题本身没有任何意义。它是基于意见的、广泛的和不清楚的。 “我认为提出我们自己的可迭代定义不是一个好主意” - 同意。 OP 没有引用 Python 对“可迭代”的定义。只是避免回答。
猜你喜欢
  • 1970-01-01
  • 2018-09-08
  • 2019-04-08
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多