我有一个这样的函数
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
- 一些用户定义的向量类等
但不是:
- str
- 字节
- 一些用户定义的 str 类用于 UTF-16 等
恐怕这是不可能的,因为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)
。
可以使用 - ABC
collections.abc.ByteString
来区分字节序列类型(如bytes
和bytearray
)。
当然,你也可以定义自己的ABC,其中包括str
和ByteString
,甚至给它一个__subclasshook__
来检查类中的方法,如capitalize
。
你的魔法叫做types.StringTypes
.它不是抽象的基类,但它是我们拥有的最好的。
从 https://docs.python.org/2/library/types.html#types.StringTypes(强调我的):
包含
StringType
和UnicodeType
的序列,用于促进 更轻松地检查任何字符串对象。使用这个更便携 而不是使用在其他地方构造的两种字符串类型的序列 因为它只包含UnicodeType
如果它是在运行中构建的 蟒蛇的版本。例如:isinstance(s, types.StringTypes)
.版本 2.2 中的新功能。