我想了解内置函数属性是如何工作的。让我困惑的是,属性也可以用作装饰器,但它只在用作内置函数时接受参数,而在用作装饰器时不接受参数。

下面的例子来自文档:

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

属性的参数是getx, setx, delx和一个doc字符串。

在下面的代码中,属性被用作装饰器。它的对象是x函数,但在上面的代码中,参数中没有对象函数的位置。

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

在本例中,如何创建x.setter和x.deleter装饰器?


当前回答

装饰器是一个函数,它接受一个函数作为参数并返回一个闭包。闭包是一组内部函数和自由变量。内部函数在自由变量上闭合,这就是为什么它被称为“闭包”。自由变量是内部函数外部的变量,通过修饰器传入内部函数。

顾名思义,decorator修饰接收到的函数。

function decorator(undecorated_func):
    print("calling decorator func")
    inner():
       print("I am inside inner")
       return undecorated_func
    return inner

这是一个简单的装饰函数。它接收到“unorated_func”并将其作为自由变量传递给inner(), inner()打印“I am inside inner”并返回unorated_func。当我们调用decorator(unorated_func)时,它将返回内部的。这里是关键,在decorator中,我们将内部函数命名为我们传递的函数的名称。

   undecorated_function= decorator(undecorated_func) 

现在内部函数被称为“unorated_func”。由于inner现在被命名为“unorated_func”,我们将“unorated_func”传递给装饰器,并返回“unorated_func”,并打印出“I am inside inner”。因此这个打印语句修饰了我们的“unorated_func”。

现在让我们定义一个带有属性装饰器的类:

class Person:
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self.value):
        self._name=value

当我们用@property()修饰name()时,发生了这样的事情:

name=property(name) # Person.__dict__ you ll see name 

property()的第一个参数是getter。这是第二次装饰的情况:

   name=name.setter(name) 

如上所述,装饰器返回内部函数,我们用传递的函数名命名内部函数。

这里有一件重要的事情需要注意。name是不可变的。在第一个装饰中,我们得到了这个:

  name=property(name)

在第二个例子中,我们得到了这个

  name=name.setter(name)

我们没有修改名称obj。在第二个修饰中,python看到这是属性对象,并且它已经有getter。因此,python创建了一个新的“name”对象,从第一个obj中添加“fget”,然后设置“fset”。

其他回答

属性可以用两种方式声明。

为属性创建getter、setter方法,然后将这些方法作为参数传递给属性函数 使用@property装饰器。

你可以看看我写的一些关于python属性的例子。

这之后:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

等于:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, _x_set, _x_del, 
                    "I'm the 'x' property.")

等于:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, doc="I'm the 'x' property.")
    x = x.setter(_x_set)
    x = x.deleter(_x_del)

等于:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x
    x = property(_x_get, doc="I'm the 'x' property.")

    def _x_set(self, value):
        self._x = value
    x = x.setter(_x_set)

    def _x_del(self):
        del self._x
    x = x.deleter(_x_del)

也就是:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

这一点已经被很多人澄清了,但这是我一直在寻找的一个直接点。 这是我认为从@property装饰器开始很重要的一点。 如:-

class UtilityMixin():
    @property
    def get_config(self):
        return "This is property"

函数“get_config()”的调用将像这样工作。

util = UtilityMixin()
print(util.get_config)

如果您注意到,我没有使用“()”括号来调用函数。这是我搜索@property装饰器的基本内容。这样你就可以像使用变量一样使用函数。

下面是@property如何实现的一个最小示例:

class Thing:
    def __init__(self, my_word):
        self._word = my_word 
    @property
    def word(self):
        return self._word

>>> print( Thing('ok').word )
'ok'

否则,word仍然是一个方法而不是属性。

class Thing:
    def __init__(self, my_word):
        self._word = my_word
    def word(self):
        return self._word

>>> print( Thing('ok').word() )
'ok'

最好的解释在这里: Python @属性解释-如何使用和何时?(例子) 作者:塞尔瓦·普拉巴卡兰|发表于2018年11月5日

它帮助我理解为什么,而不仅仅是如何。

https://www.machinelearningplus.com/python/python-property/