gpt4 book ai didi

python - python内置@property如何接收重载的setter函数?

转载 作者:太空宇宙 更新时间:2023-11-04 04:31:15 24 4
gpt4 key购买 nike

当使用@property 定义内置 python 属性时,属性对象如何区分 setter 方法和 getter 方法,前提是它们被重载(具有相同的名称)?

class A:

def __init__(self):
self._x = 12

@property
def x(self) -> int:
return self._x

@notifiable # strangely this stacks on both setter and getter
@x.setter
def x(self, val: int):
self._x = val

如果我定义一个自定义属性装饰器,说:

class my_property:
def __init__(self, getter):
print("__init__ getter %s:" % getter)

def setter(self, setter: FunctionType):
print("setter: %s" % setter)


class B:
def __init__(self):
self._val = 44

@my_property
def x(self):
return self._val

@x.setter
def x(self, val):
self._val = val

执行代码结果如下

__init__ getter <function B.x at 0x7ff80c5e1620>:
setter: <function B.x at 0x7ff80c5e1620>

传递给装饰器的 getter 和 setter 函数是相同的函数,但它们应该是不同的函数。

如果我这样使用注解:

class C:
def __init__(self):
self._val = 44

@my_property
def x(self):
return self._val

@x.setter
def set_x(self, val):
self._val = val

如预期的那样打印了一个不同的函数。

__init__ getter <function C.x at 0x7f529132c6a8>:
setter: <function C.set_x at 0x7f529132c6a8>

python 如何使用内置的@property 解决这个问题?装饰器与用户装饰器的处理方式不同吗?

最佳答案

之所以会出现这种情况,是因为您没有在任何地方保留对 getter 的引用。这意味着一旦 __init__ 方法结束,就不再有对第一个 B.x 的引用(即引用计数为零),因此函数被释放。由于原始的 getter 函数已经发布,Python 可以自由地为另一个对象/函数重用完全相同的内存地址,这就是本例中发生的情况。

如果您修改 my_property 以保留对原始 getter 方法的引用:

class my_property:
def __init__(self, getter):
print("__init__ getter %s:" % getter)
self.getter = getter

def setter(self, setter: FunctionType):
print("setter: %s" % setter)

你会看到函数名 (B.x) 仍然是相同的(这没关系,因为 python 不使用函数名来唯一标识函数),但是两个函数的内存地址不同:

__init__ getter <function B.x at 0x7f9870d60048>
setter: <function B.x at 0x7f9870d600d0>

Is the decorator treated differently from user decorators ?

不,属性只是一个普通的装饰器。但是,如果您想重新实现属性装饰器,您可能会对 descriptor protocol 感兴趣(该页面中有@property 的纯 python 重新实现)。

关于python - python内置@property如何接收重载的setter函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52608193/

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