返回实例的Python属性装饰器有什么用?

时间:2013-08-20 05:27:21

标签: python properties tornado

我看到了如下代码(来自https://github.com/daydayfree/diggit/blob/master/model/model.py):

from database import Database
...
class Model(object):
    @property
    def db(self): return Database()

    def insert(self, documents):
        return self.db.insert(self.table, documents)
...

@property的主要目的是提供Database()实例中方法的访问权限,我是否正确?

我可以将其重写为:

from database import Database
...
class Model(object):
    def __init__(self):
        self.db = Database()

    def insert(self, documents):
        return self.db.insert(self.table, documents)

from database import Database
...
class Model(object):
    def db(self):
        return Database()

    def insert(self, documents):
        return self.db().insert(self.table, documents)
...

?如果不是,它们之间有什么区别?

3 个答案:

答案 0 :(得分:1)

@property装饰器用于调用方法看起来像调用实例。

因此,如果您有一个Model实例,则可以通过调用db看起来像db属性的内容来获取数据库对象,但是实际上是db方法:

>>> a = Model()
>>> a.db
Database()

在您的第一个“重写”示例中,您可以在班级的db方法中创建__init__属性。现在,每次调用db属性时,每次都会获得相同的 Database对象(在__init__调用期间创建的对象),而不是和以前一样

想象一下,你可以用python标准库中的return Database()替换return random.random()。在原始实现中,每次调用db时都会返回一个新号码。在您建议的实施中,每次都会返回相同的数字,因为random.random()仅被调用一次(在__init__方法中),并且其输出已保存在db中。

您的第二次“重写”与原始实现基本相同,只是您将db称为方法(即使用开括号和近括号)。

>>> a = Model()
>>> a.db()
Database()

答案 1 :(得分:1)

存在差异......

方法1:属性装饰器

class Model(object):
    @property
    def db(self): return Database() 

o = Model()
db1 = o.db  #a database instance. No brackets
db2 = o.db  #another database instance
o.db = foo  #error due to read only property

每次调用db时,都会创建一个新的数据库实例。

方法2:初始化时设置db

class Model(object):
    def __init__(self):
        self.db = Database()

o = Model()
db1 = o.db  #a database instance
db2 = o.db  #the same database instance
o.db = foo  #works fine so long as foo is defined

每次访问db时,它都会返回相同的数据库实例。

方法3:db作为函数

class Model(object):
    def db(self):
        return Database()

o = Model()
db1 = o.db()  #a database instance. note the brackets
db2 = o.db()  #another database instance
o.db = foo    #works fine so long as foo is defined

每次调用db时,都会创建一个新的数据库实例。

答案 2 :(得分:0)

当它被调用时,它会创建一个新的数据库实例,类似于第二个替代实例。这意味着每次调用insert都会创建一个新的数据库实例,插入然后删除数据库实例,因为没有任何引用指向它。

在您的第一个替代方案中,您将始终访问相同的实例。这意味着在调用insert之后,Database对象仍然存在。