内置的非数据版本属性是什么?

9
class Books():
    def __init__(self):
        self.__dict__['referTable'] = 1

    @property
    def referTable(self):
        return 2

book = Books()
print(book.referTable)
print(book.__dict__['referTable'])

运行中:

vic@ubuntu:~/Desktop$ python3 test.py 
2
1

Books.referTable 作为数据描述符没有被book.__dict__['referTable']覆盖:

property()函数是作为数据描述符实现的。因此,实例不能覆盖属性的行为。

要进行覆盖,我必须使用自己的描述符而不是内置的property描述符。是否有像property一样但不是数据描述符的内置描述符?


1
你在这里想要做什么?你想要实现什么,而不能通过改变你正在使用的函数上的“@property”方式来实现? - Gareth Latty
@Lattyware,我正在尝试创建一个lazy descriptor。有时我希望在__init__中设置referTable。在其他情况下,我希望描述符计算该值并覆盖描述符,就像在__init__中所做的那样。在这里(http://blog.pythonisito.com/2008/08/lazy-descriptors.html)为此创建了一个单独的描述符,这对我很有用。在我的情况下,如果可能的话,我想简化它,使用内置描述符,但`property`对我不起作用。 - warvariuc
“简化它”?您能澄清您想要简化什么吗?为什么您提供的链接示例对您无效? - Gareth Latty
如果property是一个非数据描述符,我可以使用它来代替自己编写的描述符。这是我的简化。只是好奇是否存在标准模块中的非数据版本的property。这就是全部。我的问题不是关于解决方法的。 - warvariuc
2个回答

5
为了进一步解释我的评论,为什么不简单地做这样的事情:
>>> class Books():
...     def __init__(self):
...         self.__dict__['referTable'] = 1
...     @property
...     def referTable(self):
...         try:
...             return self.__dict__['referTable']
...         except KeyError:
...             return 2
... 
>>> a = Books()
>>> a.referTable
1
>>> del a.__dict__['referTable']
>>> a.referTable
2

现在,我想提醒大家的是,我认为这并不是一个好的设计,你最好使用私有变量而不是直接访问__dict__。例如:

class Books():
    def __init__(self):
        self._referTable = 1

    @property
    def referTable(self):
        return self._referTable if self._referTable else 2

简而言之,答案是否定的,在Python标准库中没有其他可替代property()并以您所需的方式运行的选项。

2

有一种非常类似于内置的非数据描述符 - 类属性:

class Books():

    referTable = 'default'

    def __init__(self, referTable=None):
        if referTable is not None:
            self.referTable = referTable


book = Books()
print(book.referTable)
# default
book.referTable = 'something specific'
print(book.referTable)
# something specific

如果您需要更像属性的东西(例如,您希望函数在第一次执行时进行一些重要操作,然后将该值用于所有未来引用),那么您需要自己构建它:
class OneTime(object):

    def __init__(self, method):
        self.name = method.__name__
        self.method = method

    def __get__(self, inst, cls):
        if inst is None:
            return self
        result = self.method(inst)
        inst.__dict__[self.name] = result
        return result

class Books(object):

    @OneTime
    def referTable(self):
        print 'calculating'
        return 1 * 2 * 3 * 4 * 5

b = Books()
print b.__dict__
print b.referTable
print b.__dict__
print b.referTable

以下是结果:
{}
calculating
120
{'referTable': 120}
120

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接