有没有一种 pythonics 方法来区分像 "tuple and list" 这样的序列对象和像 "bytes and str" 这样的序列对象
is there a pythonics way to distinguish Sequences objects like "tuple and list" from Sequence objects like "bytes and str"
我有这样一个功能
def print_stuff(items):
if isinstance(items, (str, bytes)):
items = (items,)
for item in items:
print (item)
可以这样调用:
In [37]: print_stuff(('a', 'b'))
a
b
In [38]: print_stuff('a')
a
我不喜欢 isinstance (items, (str, bytes))
我更愿意 isinstance(item, (collections.abc.MAGIC))
其中 MAGIC 是所有序列对象的 ABC,可以包含其他序列对象,例如
- 元组
- 列表
- numpy.array
- 一些用户定义的矢量 class,等等
但不是:
- 海峡
- 字节
- 一些用户为 UTF-16 等定义的字符串 class
恐怕这是不可能的,因为 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]
好问题。
- (目前)没有区分字符串与元组或其他不可变序列的 ABC;因为 Python 3 中只有一种字符串类型,所以最 Pythonic 的解决方案确实是
isinstance(x, str)
.
- 字节序列类型如
bytes
和bytearray
可以使用collections.abc.ByteString
ABC来区分。
当然,您也可以定义自己的 ABC,其中包括 str
和 ByteString
,甚至给它一个 __subclasshook__
来检查 类 的方法比如capitalize
.
你的魔法叫做types.StringTypes
。它不是抽象基础 class 但它是我们拥有的最好的基础。
来自 https://docs.python.org/2/library/types.html#types.StringTypes(强调我的):
A sequence containing StringType
and UnicodeType
used to facilitate
easier checking for any string object. Using this is more portable
than using a sequence of the two string types constructed elsewhere
since it only contains UnicodeType
if it has been built in the running
version of Python. For example: isinstance(s, types.StringTypes)
.
New in version 2.2.
我有这样一个功能
def print_stuff(items):
if isinstance(items, (str, bytes)):
items = (items,)
for item in items:
print (item)
可以这样调用:
In [37]: print_stuff(('a', 'b'))
a
b
In [38]: print_stuff('a')
a
我不喜欢 isinstance (items, (str, bytes))
我更愿意 isinstance(item, (collections.abc.MAGIC))
其中 MAGIC 是所有序列对象的 ABC,可以包含其他序列对象,例如
- 元组
- 列表
- numpy.array
- 一些用户定义的矢量 class,等等
但不是:
- 海峡
- 字节
- 一些用户为 UTF-16 等定义的字符串 class
恐怕这是不可能的,因为 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]
好问题。
- (目前)没有区分字符串与元组或其他不可变序列的 ABC;因为 Python 3 中只有一种字符串类型,所以最 Pythonic 的解决方案确实是
isinstance(x, str)
. - 字节序列类型如
bytes
和bytearray
可以使用collections.abc.ByteString
ABC来区分。
当然,您也可以定义自己的 ABC,其中包括 str
和 ByteString
,甚至给它一个 __subclasshook__
来检查 类 的方法比如capitalize
.
你的魔法叫做types.StringTypes
。它不是抽象基础 class 但它是我们拥有的最好的基础。
来自 https://docs.python.org/2/library/types.html#types.StringTypes(强调我的):
A sequence containing
StringType
andUnicodeType
used to facilitate easier checking for any string object. Using this is more portable than using a sequence of the two string types constructed elsewhere since it only containsUnicodeType
if it has been built in the running version of Python. For example:isinstance(s, types.StringTypes)
.New in version 2.2.