属性装饰器如何在Python中使用语法糖(@)在内部工作?

Sor*_*ary 6 python properties decorator

我知道我的问题似乎与其他人非常相似。但事实并非如此,我搜索了很多却找不到答案。

据我们所知:

@mydecorator
def myfn():
    pass
Run Code Online (Sandbox Code Playgroud)

(确切地说?)翻译为:

def myfn():
    pass
myfn = mydecorator(myfn)
Run Code Online (Sandbox Code Playgroud)

考虑下面的类:

class C:
def __init__(self, language):
    self._language = language

@property
def language(self):
    return self._language

@language.setter
def language(self, value):
    self._language = value
Run Code Online (Sandbox Code Playgroud)

如果我们想将它们翻译为函数+赋值语句,对于 getter 来说没有问题:

def language(self):
    return self._language
language = property(language)
Run Code Online (Sandbox Code Playgroud)

但是二传手呢?:

def language(self, value):
    self._language = value
language = language.setter(language)
Run Code Online (Sandbox Code Playgroud)

我做了我以前做过的事情,但这行不通。在上一阶段(getter)之后,标签“语言”引用属性对象。现在它被重新分配给一个函数(函数优先)!所以这个 language.setter 不起作用,它不再是一个属性。

我想当我们使用@语法时可能有一个额外的步骤。如果是,那是什么?我们可以说它们彼此大致相似吗?

如果不是,例如,当我们将装饰器与属性对象一起使用时,它们的行为不仅仅是转换为函数+赋值语句?

Thi*_*lle 2

区别就在于你问自己是否相同(exactly?)

PEP 318快速提到了这一点:

当前语法

Python 2.4a2 中实现的函数装饰器的当前语法是:

@dec2
@dec1
def func(arg1, arg2, ...):
    pass
Run Code Online (Sandbox Code Playgroud)

这相当于:

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))
Run Code Online (Sandbox Code Playgroud)

无需对变量 func 进行中间赋值。(强调我的)

因此,这就是为什么当您使用该语法时一切正常的原因@decorator

您可以通过使用不同的名称来使其工作:

class C:
    def __init__(self, language):
        self._language = language

    
    def language(self):
        return self._language
    language = property(language)
    
    
    def dummy_temporary_name(self, value):
        self._language = value
    language = language.setter(dummy_temporary_name)
    
    
c = C('fr')
print(c.language)
c.language = 'de'
print(c.language)

# fr
# de
Run Code Online (Sandbox Code Playgroud)