为什么从抽象基类继承时,Python2和Python3中的插槽行为不同
我创建了下面的类来以内存高效的方式存储平面上的可变点-我需要一个可变的等价物为什么从抽象基类继承时,Python2和Python3中的插槽行为不同,python,python-3.x,python-2.x,abstract-base-class,Python,Python 3.x,Python 2.x,Abstract Base Class,我创建了下面的类来以内存高效的方式存储平面上的可变点-我需要一个可变的等价物namedtuple('Point','xy')。由于实例字典很大,我想我应该选择\uuuuuuuuuuuuuuu: from collections import Sequence class Point(Sequence): __slots__ = ('x', 'y') def __init__(self, x=0, y=0): self.x = x self.y
namedtuple('Point','xy')
。由于实例字典很大,我想我应该选择\uuuuuuuuuuuuuuu
:
from collections import Sequence
class Point(Sequence):
__slots__ = ('x', 'y')
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __getitem__(self, item):
return getattr(self, self.__slots__[item])
def __setitem__(self, item, value):
return setattr(self, self.__slots__[item], value)
def __repr__(self):
return 'Point(x=%r, y=%r)' % (self.x, self.y)
def __len__(self):
return 2
在Python 3上测试时,一切似乎都正常:
>>> pt = Point(12, 42)
>>> pt[0], pt.y
(12, 42)
>>> pt.x = 5
>>> pt
Point(x=5, y=42)
>>> pt.z = 6
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Point' object has no attribute 'z'
为什么会这样,为什么Python2和Python3之间存在差异?Python2数据模型说:
- 当从没有
的类继承时,该类的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
属性将始终是可访问的,因此子类中的\uuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuuuuuuu
集合
模块中的抽象基类根本没有\uuuuu插槽
:
>>> from collections import Sequence
>>> Sequence.__slots__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'Sequence' has no attribute '__slots__'
因此,在Python2中,您不能从
集合
基类继承,同时使用\uuuu插槽
进行内存高效存储
然而,请注意,即使索赔文件 这些ABC允许我们询问类或实例是否提供特定功能,例如:
size = None
if isinstance(myvar, collections.Sized):
size = len(myvar)
);简单地实现序列所需的所有方法不会使类的实例通过isinstance
检查
原因是该类没有;如果没有它,则参考父类\uuuuu子类hook\uuuu
;在这种情况下;如果针对类测试的大小不准确,则返回NotImplemented
另一方面,人们无法通过魔法方法来区分映射类型和序列类型,因为它们都可以拥有完全相同的魔法方法-集合的
但是,您仍然不需要从Sequence
继承以使isinstance(点,序列)
返回True
。在下面的示例中,点
是相同的,除了在Python 2上从对象
而不是从序列
派生之外:
>>> pt = Point(12, 42)
>>> pt.z = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Point' object has no attribute 'z'
>>> isinstance(pt, Sequence)
False
>>> Sequence.register(pt)
>>> isinstance(pt, Sequence)
True
>pt=点(12,42)
>>>第z部分=5
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“点”对象没有属性“z”
>>>isinstance(pt,序列)
假的
>>>顺序寄存器(pt)
>>>isinstance(pt,序列)
真的
您可以将任何类注册为抽象基类的子类,以进行isinstance
检查;在额外的混合方法中,您实际上只需要实现count
和index
;其他功能将由Python运行时填充
size = None
if isinstance(myvar, collections.Sized):
size = len(myvar)
>>> pt = Point(12, 42)
>>> pt.z = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Point' object has no attribute 'z'
>>> isinstance(pt, Sequence)
False
>>> Sequence.register(pt)
>>> isinstance(pt, Sequence)
True