gpt4 book ai didi

使用自定义 __setattr__ 和 __slots__ 进行 Python 属性查找

转载 作者:行者123 更新时间:2023-11-28 22:24:45 25 4
gpt4 key购买 nike

我有一个类使用 __slots__ 并通过覆盖 __setattr__ 使它们几乎不可变以始终引发错误:

class A:
__slots__ = ['a', 'b', '_x']

def __init__(self, a, b):
object.__setattr__(self, 'a', a)
object.__setattr__(self, 'b', b)

def __setattr__(self, attr, value):
raise AttributeError('Immutable!')

@property
def x():
return self._x

@x.setter
def x(value):
object.__setattr__(self, '_x', value)

在这里,“私有(private)”属性 _x 是一个占位符,用于与某些自定义硬件交互的复杂操作。

因为 x 是一个属性,我希望能够做类似的事情

 inst = A(1, 2)
inst.x = 3

相反,我看到了带有消息 Immutable!AttributeError

这里有许多明显的解决方法,例如删除自定义 __setattr__(我不想这样做)或将其重写为

def __setattr__(self, attr, value):
if attr != 'x':
raise AttributeError('Immutable!')
super().__setattr__(attr, value)

这似乎是一种笨拙的方法,如果我开始添加更多类似的属性,它可能会膨胀得不成比例。

真正的问题是我不明白为什么__slots__和属性之间没有冲突,但是__setattr__和属性之间有冲突。查找顺序发生了什么,是否有另一种更优雅的解决方法来解决这个问题?

最佳答案

The real issue is that I do not understand why there is no conflict between __slots__ and the property, but there is one between __setattr__ and the property.

__slots__property 都通过提供 descriptor 来实现属性查找。对于相应的属性。 __slots__ 的存在不是通过对 __setattr__ 做任何事情来阻止任意实例属性的创建,而是通过阻止创建 __dict__property 和其他描述符不依赖实例 __dict__,因此它们不受影响。

但是,__setattr__ 处理所有 属性赋值,这意味着描述符调用是__setattr__ 的责任。如果您的 __setattr__ 不处理描述符,则不会处理描述符,并且不会调用 property setter。

is there another, more elegant workaround to this problem?

你可以明确地只允许属性:

class A:
...
def __setattr__(self, name, value):
if not isinstance(getattr(type(self), name, None), property):
raise AttributeError("Can't assign to attribute " + name)
super().__setattr__(name, value)

或者您可以明确拒绝分配给插槽,并将其他属性分配委托(delegate)给 super().__setattr__:

class A:
...
def __setattr__(self, name, value):
if isinstance(getattr(type(self), name, None), _SlotDescriptorType):
raise AttributeError("Can't assign to slot " + name)
super().__setattr__(name, value)

# Seems to be the same as types.MemberDescriptorType,
# but the docs don't guarantee it.
_SlotDescriptorType = type(A.a)

关于使用自定义 __setattr__ 和 __slots__ 进行 Python 属性查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46101056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com