删除器中的事件链
Chain of events in a deleter
假设我有以下 class 与客户 deleter
的属性和实例本身:
class Hello:
def __init__(self):
self._is_open = None
@property
def is_open(self):
return self._is_open
@is_open.deleter
def is_open(self):
print("Using custom deleter!")
del self._is_open
def __delattr__(self, attr):
print ('Deleting attr %s' % attr)
super().__delattr__(attr)
并调用它:
>>> hello = Hello()
>>> del hello.is_open
Deleting attr is_open
Using custom deleter!
Deleting attr _is_open
看起来它首先在 is_open
上调用 __delattr__
,然后调用 @is_open.deleter
,然后在 _is_open
上调用 __delattr__
。为什么删除者的事件链会这样?
Python properties are descriptors. They are implemented via descriptor protocol.
数据模型挂钩 __delattr__
优先于描述符协议。因此,如果您定义了自定义 __delattr__
方法,那么将优先调用 属性 删除器。
事实上,它是 __delattr__
的默认实现,它会在必要时调用描述符,您可以通过注释掉以 super
开头的行来验证这一点(您应该看到属性 删除器现在根本不会被调用)。
有了这个推理,您就可以理解这样的事件链:
Deleting attr is_open
# the del statement `del hello.is_open` is directly invoking Hello.__delattr__,
# passing in attr="is_open" as argument
# Now, the implementation of `Hello.__delattr__` calls
# `super().__delattr__(attr)`, passing along the argument attr="is_open", which
# then invokes a descriptor for that attribute (i.e. the function
# `Hello.is_open.fdel` is about to be called)
Using custom deleter!
# This comes from within the property (`Hello.is_open`) deleter.
Deleting attr _is_open
# The implementation of the `is_open` deleter actually uses another del
# statement, i.e. `del self._is_open`. This invokes again `Hello.__delattr__`,
# passing attr="_is_open" as an argument. However, this time there is no
# descriptor with the name `_is_open` present so an attribute gets deleted from
# the instance namespace instead. Note that the attribute `self._is_open` was
# there in `self.__dict__` already because it gets created during the __init__
# method when `hello = Hello()` is executed.
重要的是要注意 __delattr__
第一次和第二次收到不同的参数:首先 "is_open"
然后 "_is_open"
第二。
假设我有以下 class 与客户 deleter
的属性和实例本身:
class Hello:
def __init__(self):
self._is_open = None
@property
def is_open(self):
return self._is_open
@is_open.deleter
def is_open(self):
print("Using custom deleter!")
del self._is_open
def __delattr__(self, attr):
print ('Deleting attr %s' % attr)
super().__delattr__(attr)
并调用它:
>>> hello = Hello()
>>> del hello.is_open
Deleting attr is_open
Using custom deleter!
Deleting attr _is_open
看起来它首先在 is_open
上调用 __delattr__
,然后调用 @is_open.deleter
,然后在 _is_open
上调用 __delattr__
。为什么删除者的事件链会这样?
Python properties are descriptors. They are implemented via descriptor protocol.
数据模型挂钩 __delattr__
优先于描述符协议。因此,如果您定义了自定义 __delattr__
方法,那么将优先调用 属性 删除器。
事实上,它是 __delattr__
的默认实现,它会在必要时调用描述符,您可以通过注释掉以 super
开头的行来验证这一点(您应该看到属性 删除器现在根本不会被调用)。
有了这个推理,您就可以理解这样的事件链:
Deleting attr is_open
# the del statement `del hello.is_open` is directly invoking Hello.__delattr__,
# passing in attr="is_open" as argument
# Now, the implementation of `Hello.__delattr__` calls
# `super().__delattr__(attr)`, passing along the argument attr="is_open", which
# then invokes a descriptor for that attribute (i.e. the function
# `Hello.is_open.fdel` is about to be called)
Using custom deleter!
# This comes from within the property (`Hello.is_open`) deleter.
Deleting attr _is_open
# The implementation of the `is_open` deleter actually uses another del
# statement, i.e. `del self._is_open`. This invokes again `Hello.__delattr__`,
# passing attr="_is_open" as an argument. However, this time there is no
# descriptor with the name `_is_open` present so an attribute gets deleted from
# the instance namespace instead. Note that the attribute `self._is_open` was
# there in `self.__dict__` already because it gets created during the __init__
# method when `hello = Hello()` is executed.
重要的是要注意 __delattr__
第一次和第二次收到不同的参数:首先 "is_open"
然后 "_is_open"
第二。