重写的属性访问不起作用(如预期的那样)

时间:2009-12-09 13:52:35

标签: python attributes setattr

以下模块的主要目的是为某些名称提供一种“常量”语义。

class ConstantError(Exception):

    def __init__(self, msg):
            self._msg = msg


class Constant(object):

    def __init__(self, name):
            self._name = name

    def __get__(self, instance, owner):
            return instance._content[self._name]

    def __set__(self, instance, value):
            raise ConstantError, 'Illegal use of constant'


class Constants(object):

    def __init__(self, content):
            self._content = content
            for k in self._content:
                    setattr(self, k, Constant(k))

num_const = Constants({
    'one': 1,
    'two': 2
})

使用时:

>>> from const import *
>>> dir(num_const)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_content', 'one', 'two']

所以onetwo就在那里,但属性访问是对立的:

>>> num_const.one
<const.Constant object at 0x7faef4871710>
>>> 

在这种情况下我期望1。我哪里错了?

3 个答案:

答案 0 :(得分:3)

描述符协议仅适用于类属性,而不适用于类实例的属性。请参阅How-To Guide for Descriptors

答案 1 :(得分:0)

您在常量中缺少 str ()或 unicode ()方法。

添加:

def __unicode__(self):
    return self._name

答案 2 :(得分:0)

我认为python会阻止类访问描述符机制,以便可以对它们进行操作。否则操作描述符可能会变得非常棘手,没有某种“魔法”功能,如果你注意到python试图保持很多语言机制可访问。为了解决这个问题,我经常在课堂上创建课程。例如,您可以像这样声明Constants类:

class Constants(object):
    def __new__(cls, content):
       class _Constants(object):
           pass
       constants = _Constants
       constants._content = content
       for k in constants._content:
            setattr(_Constants, k, Constant(k))
       return constants

但实际上,为了您的目的,您可能会更好:

class Constants(object):
    def __init__(self, content):
       self._content = content
    def __getattr__(self,key):
       return self._content[key]