我注意到了一些我不完全理解的奇怪的行为。出于性能原因,我在类中使用时隙。为什么简单的类变量赋值很容易破坏所有的类实例?
class Person:
__slots__ = ('name',)
def __init__(self, name) -> None:
self.name = name
def __repr__(self):
return self.name
p1 = Person('mc')
p2 = Person('pp')
# The nasty thing here:
Person.name = 'hacked'
print(p1)
print(p2)因此,所有实例的“名称”属性都会被覆盖。不应该由翻译来阻止吗?当您想要显式定义一个与插槽中使用的名称相同的类变量时,情况就是如此。
我有点困惑,因为它看起来太容易发生意外损害。
发布于 2021-09-15 15:38:27
当您这样做时,您正在破坏__slots__的实现:
Person.name = 'hacked'来自文档
__slots__是通过为每个变量名创建描述符(实现描述符)在类级别上实现的。因此,类属性不能用于为__slots__定义的实例变量设置默认值;否则,类属性将覆盖描述符赋值。
这意味着创建类时Person.name实际上是一个<class 'member_descriptor'>。在你的‘黑客’之后,它变成了一个正常的str。您可以通过在“黑客”之前和之后打印type(Person.name)来检查这一点。
__slots__以微妙的方式更改类行为,因此在使用它之前仔细阅读文档。
https://stackoverflow.com/questions/69195895
复制相似问题