Django的@property有什么作用?

时间:2019-10-25 12:58:25

标签: python django

在Django中@property是什么?

这是我的理解:@property是用于获取方法中值的类中方法的修饰符。

但是,据我了解,我可以像平常一样调用该方法,它将得到它。所以我不确定它到底是做什么的。

文档示例:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        elif self.birth_date < datetime.date(1965, 1, 1):
            return "Baby boomer"
        else:
            return "Post-boomer"

    @property
    def full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)

如果有与没有,有什么区别?

2 个答案:

答案 0 :(得分:2)

如您所见,功能full_name返回一个字符串,其中包含人的名字和姓氏。

@property装饰器的作用是声明可以像常规属性一样对其进行访问。

这意味着您可以像对待成员变量而不是函数一样调用first_name,就像这样:

name = person.full_name

代替

name = person.full_name()

您还可以定义如下的setter方法:

@full_name.setter
def full_name(self, value):
     names = value.split(' ')
     self.first_name = names[0]
     self.last_name = names[1]

使用此方法,您可以这样设置人员的全名:

person.full_name = 'John Doe'

代替

person.set_full_name('John Doe')

P.S。上面的setter只是一个示例,因为它仅适用于由两个用空格分隔的单词组成的名称。在现实生活中,您将使用更强大的功能。

答案 1 :(得分:1)

在某些语言中,鼓励用户将属性设为私有并创建公共的getter和setter方法,例如用privatepublic组成的类似Python的语言:

class Foo:
    private bar

    public get_bar(bar):
        return self.bar  # or look it up in a database
                         # or compute it on the fly from other values
                         # or anything else

    public set_bar(new_bar):
        self.bar = new_bar

该论据是关于提供一个稳定的接口。如果您想更改班级的内部运作方式,例如从数据库中查找或计算它,该类的用户无需更改任何内容;他们只是一直在呼叫getter和setter。

在Python中,我们实际上没有私有属性,我们需要简单的语法。因此,我们将其翻转:程序员经常直接访问对象的属性。但是,如果您想更改内部行为,该怎么办?我们不想更改类的界面。

@property使您可以更改bar内部的工作方式,而无需更改外部接口。该类的用户仍然可以访问foo.bar,但是您的内部逻辑可以完全不同:

class Foo:
    def __init__(self, bar):
        self.bar = bar

def main():
    f = Foo()
    print(f.bar)

# Later we can change to something this without breaking other code
class Foo:
    def __init__(self, bar):
        self.save_bar_to_database(bar)  # Or anything else

    @property
    def bar(self):
        return self.load_bar_from_database()