Jai*_*ime 12 python bytearray abc python-internals
我看到Python 2和3之间的行为有一种奇怪的差异.
在Python 3中,似乎工作正常:
Python 3.5.0rc2 (v3.5.0rc2:cc15d736d860, Aug 25 2015, 04:45:41) [MSC v.1900 32 b
it (Intel)] on win32
>>> from collections import Sequence
>>> isinstance(bytearray(b"56"), Sequence)
True
Run Code Online (Sandbox Code Playgroud)
但不是在Python 2中:
Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on wi
n32
>>> from collections import Sequence
>>> isinstance(bytearray("56"), Sequence)
False
Run Code Online (Sandbox Code Playgroud)
在Python 2.x和3.x的次要版本中,结果似乎是一致的.这是一个已知的错误?它是一个bug吗?这种差异背后有什么逻辑吗?
我实际上更担心C API函数PySequence_Check正确识别类型的对象,PyByteArray_Type因为它暴露了序列协议,通过查看它看起来应该的源代码,但是对这整个事物的任何洞察都是非常受欢迎的.
抽象类从collections使用ABCMeta.register(subclass)到
将子类注册为此ABC的"虚拟子类".
在Python 3中issubclass(bytearray, Sequence)返回True因为bytearray显式注册为子类ByteString(派生自Sequence)和MutableSequence.请参阅Lib/_collections_abc.py的相关部分:
class ByteString(Sequence):
"""This unifies bytes and bytearray.
XXX Should add all their methods.
"""
__slots__ = ()
ByteString.register(bytes)
ByteString.register(bytearray)
...
MutableSequence.register(bytearray) # Multiply inheriting, see ByteString
Run Code Online (Sandbox Code Playgroud)
Python 2没有这样做(来自Lib/_abcoll.py):
Sequence.register(tuple)
Sequence.register(basestring)
Sequence.register(buffer)
Sequence.register(xrange)
...
MutableSequence.register(list)
Run Code Online (Sandbox Code Playgroud)
在Python 3.0中更改了此行为(在此提交中):
添加ABC ByteString,它统一了字节和bytearray(但不是内存视图)."PEP 3118样式缓冲API对象"没有ABC,因为在Python中无法识别这些(除了尝试 在它们上使用memoryview()).
PEP 3119中有更多信息:
这是向Python 3000添加抽象基类(ABC)支持的提议.它建议:[...]容器和迭代器的特定ABC,将添加到集合模块.
进入提案的大部分思路都不是关于ABCs的具体机制,与接口或通用功能(GF)相比,而是关于澄清哲学问题,如"什么使一组","什么使映射"和"什么使序列".
[...]一个与ABC一起使用的元类,它允许我们将ABC作为"虚拟基类"(与C++中的概念不同)添加到任何类,包括另一个类.这允许标准库定义ABCs Sequence和MutableSequence并将它们注册为内置类型(如basestring,tuple和list)的虚拟基类,以便例如以下条件都为真:[...] issubclass(bytearray, MutableSequence).
只是FYI memoryview被注册为Sequence仅在Python 3.4中的子类:
由于序列/映射混淆,因此没有出现这种情况,因此这是一个简单的缺少显式注册.
(详情请参见issue18690).
PySequence_Check来自Python C API不依赖于collections模块:
int
PySequence_Check(PyObject *s)
{
if (PyDict_Check(s))
return 0;
return s != NULL && s->ob_type->tp_as_sequence &&
s->ob_type->tp_as_sequence->sq_item != NULL;
}
Run Code Online (Sandbox Code Playgroud)
它检查非零tp_as_sequence字段(示例为bytearray),如果成功,则检查非零sq_item字段(基本上是getitem - 示例bytearray).
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |