内置非数据版本的属性?

时间:2012-04-29 17:41:14

标签: python

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 being a data descriptor未被book.__dict__['referTable']隐藏:

  

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

要遮蔽它,而不是property内置描述符,我必须使用自己的描述符。是否有内置描述符,如property,但它是非数据?

2 个答案:

答案 0 :(得分: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__。 E.g:

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

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

简而言之,答案是否定的,除了property()之外没有其他方法可以在Python标准库中以您想要的方式工作。

答案 1 :(得分:2)

与内置的非数据描述符非常相似 - 类属性:

class Person {
  // constructor function here
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  // static getter instead of a static property
  static get species() {
    return 'human';
  }
}

class Student extends Person {
   constructor(name, age, school) {
      // calling the superclass constructor
      super(name, age);
      this.school = school;
   }
}

如果你需要更像属性的东西(例如,你想要一个函数在第一次做一些繁重的工作,但是然后将所有的第一个值用于所有未来的引用),那么你需要自己构建它:

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