【问题标题】:accessing value of a python @property from a subclass从子类访问 python @property 的值
【发布时间】:2015-10-31 09:45:57
【问题描述】:

我正在尝试将 oauthlib 实现重新设计为金字塔应用程序,但在 @property 装饰类定义中遇到了一些默认值问题。

我以某种方式暴露了属性对象,而不是调用/执行它们。

谁能提出一个“执行”这些属性的好方法?似乎用任何对象调用fget/无:

self.propertyname.fget(self)

但这似乎很尴尬——就像整个问题一样。我似乎以错误的方式实现了某些东西。

这个问题的上下文是尝试从配置字典中加载一些值并返回到基类的属性上。基本形式如下,我们很乐意接受有关更好实施的建议。

class Parent(object):
    @property
    def fieldname(self):
        """returns a tuple"""
        return (1, 10)

class Child(Parent):
    @property
    def fieldname(self):
        """returns a tuple"""
        return self._config.get('fieldname', 
                                Parent.fieldname
                                )

【问题讨论】:

  • 你试过super(Child, self).fieldname吗?
  • “我以某种方式暴露了属性对象,而不是调用/执行它们。” - 那是什么意思?您现在如何在代码中调用它们,发生了什么,应该发生什么?
  • 我正在调用Parent.fieldname,它返回一个属性对象(即<property object at 0x1007a5788>)。我打算打电话给Parent().fieldname,但是使用super() 效果更好。

标签: python python-2.7 properties descriptor


【解决方案1】:

property 对象是descriptors,这意味着它们在作为属性访问时会自动绑定到实例(这也是方法的创建方式)。

如果您想访问父 property 对象,您可以通过调用 descriptor.__get__() 方法并传入 self 来手动绑定它:

Parent.fieldname.__get__(self))

property.fget() 方法只是原始的、未修饰的函数对象。你会像任何未绑定的方法一样调用它,你会再次手动传入self

Parent.fieldname.fget(self)

或者像方法一样绑定它,然后调用:

Parent.fieldname.fget.__get__(self)()

最后但同样重要的是,您可以使用super() object 为您处理绑定:

super(Child, self).fieldname

它在类层次结构的 MRO(方法解析顺序)中查找下一个具有 fieldname 属性的对象,并像上面的显式示例一样绑定它。

就个人而言,我更喜欢super() 选项;最好记录您要访问的原始属性,现在已被覆盖。

演示:

>>> class Parent(object):
...     @property
...     def fieldname(self):
...         """returns a tuple"""
...         return (1, 10)
... 
>>> class Child(Parent):
...     @property
...     def fieldname(self):
...         """returns a tuple"""
...         return self._config.get(
...             'fieldname', 
...             super(Child, self).fieldname)
... 
>>> child = Child()
>>> child._config = {}
>>> child.fieldname
(1, 10)
>>> child._config['fieldname'] = ('foo', 'bar')
>>> child.fieldname
('foo', 'bar')

【讨论】:

  • 谢谢。 super(Child, self).fieldname 有效。我也意识到我的困惑是什么——我试图调用Parent.fieldname,就好像它是一个类方法......而不是Parent().fieldname——这正是我想要的。
  • 这仅适用于该特定属性未使用self。您正在创建一个新实例并访问其上的属性(在将其绑定到该独立新实例的过程中)。
  • 没错。父包选择不使用任何类变量,并通过 @property 装饰器通过类方法公开所有内容。实例与这些问题无关,类才是最重要的。尽管如此,我还是使用了更正确的super 方法。
猜你喜欢
  • 2019-04-02
  • 1970-01-01
  • 2013-09-01
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多