是否有一种python方式将“对象和列表”之类的“序列”对象与“字节和str”之类的“序列”对象区分开来

jcr*_*jcr 6 abc python-3.x

我有这样的功能

def print_stuff(items):
    if isinstance(items, (str, bytes)):
        items = (items,)
    for item in items:
        print (item)
Run Code Online (Sandbox Code Playgroud)

可以这样称呼:

In [37]: print_stuff(('a', 'b'))
a
b

In [38]: print_stuff('a')
a
Run Code Online (Sandbox Code Playgroud)

我不喜欢做,isinstance (items, (str, bytes))我更愿意做isinstance(item, (collections.abc.MAGIC))

其中MAGIC是所有序列对象的ABC,可以包含其他序列对象,例如

  • 元组
  • 清单
  • numpy.array
  • 一些用户定义的矢量类,等等

但不是:

  • 力量
  • 个字节
  • 一些用户定义的UTF-16的str类,等等

恐怕这是不可能的,tuple并且str具有相同的7个ABC :(

In [49]: [v for k, v in vars(collections.abc).items()
    ...:                                   if inspect.isclass(v) and issubclass(tuple, v) ]
Out[49]:
[collections.abc.Hashable,
 collections.abc.Iterable,
 collections.abc.Reversible,
 collections.abc.Sized,
 collections.abc.Container,
 collections.abc.Collection,
 collections.abc.Sequence]

In [50]: [v for k, v in vars(collections.abc).items()
    ...:                                   if inspect.isclass(v) and issubclass(list, v) ]
Out[50]:
[collections.abc.Iterable,
 collections.abc.Reversible,
 collections.abc.Sized,
 collections.abc.Container,
 collections.abc.Collection,
 collections.abc.Sequence,
 collections.abc.MutableSequence]

In [51]: [v for k, v in vars(collections.abc).items()
    ...:                                   if inspect.isclass(v) and issubclass(str, v) ]
Out[51]:
[collections.abc.Hashable,
 collections.abc.Iterable,
 collections.abc.Reversible,
 collections.abc.Sized,
 collections.abc.Container,
 collections.abc.Collection,
 collections.abc.Sequence]
Run Code Online (Sandbox Code Playgroud)

Uri*_*nta 5

好问题。

  • (目前)没有 ABC 可以区分字符串与元组或其他不可变序列;由于 Python 3 中只有一种字符串类型,因此最 Pythonic 的解决方案确实是使用isinstance(x, str).
  • 字节序列类型如bytesbytearray可以使用ABC来区分collections.abc.ByteString

当然,您也可以定义自己的 ABC,其中包括strByteString,甚至给它一个__subclasshook__来检查类中的方法,例如capitalize