控制python类的getter和setter

时间:2009-08-06 21:46:56

标签: python

考虑以下课程:

class Token:
    def __init__(self):
        self.d_dict = {}

    def __setattr__(self, s_name, value):
        self.d_dict[s_name] = value

    def __getattr__(self, s_name):
        if s_name in self.d_dict.keys():
            return self.d_dict[s_name]
        else:
            raise AttributeError('No attribute {0} found !'.format(s_name))

在我的代码中Token有一些其他函数(比如get_all()返回d_dict,has(s_name)告诉我我的令牌是否有特定的属性)。

无论如何,我认为他们的计划存在缺陷,因为它不起作用:当我创建一个新实例时,python尝试调用__setattr__('d_dict', '{}')

我怎样才能实现类似的行为(可能以更加pythonic的方式?)而不必编写类似Token.set(name,value)和get(name)的东西,我想设置或获取令牌的属性

关于设计缺陷和/或愚蠢的批评欢迎:)

谢谢!

6 个答案:

答案 0 :(得分:3)

你需要特殊情况d_dict。

虽然当然,在上面的代码中,你所做的就是复制任何对象已经用__dict__做的事情,所以这是毫无意义的。如果您打算在特殊情况下使用某些属性并对其进行实际使用方法,我是否正确猜测?

在这种情况下,您可以使用属性。

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

答案 1 :(得分:3)

__dict__的特殊外壳是这样的:

def __init__(self):
    self.__dict__['d_dict'] = {}

没有必要使用新式的类。

答案 2 :(得分:2)

问题似乎是在__init__方法中评估您的代码时。 你可以定义__new__方法并在那里初始化d_dict变量而不是__init__。 这有点hackish但它的确有效,请记住,虽然几个月后它会被评论为完全神奇。

>>> class  Foo(object):
...     def __new__(cls, *args):
...             my_cls = super(Foo, cls).__new__(cls, *args)
...             my_cls.d_dict = {}
...             return my_cls

>>> f = Foo()
>>> id(f.d_dict)
3077948796L
>>> d = Foo()
>>> id(d.d_dict)
3078142804L

解释为什么我认为这样的hackish:调用__new__返回 class 的新实例,然后 d_dict 初始化中有 static ,但每次类“创建”时,它都会使用新的字典实例进行初始化,因此一切都可以根据需要运行。

答案 3 :(得分:1)

解决方案,不是非常pythonic但有效。正如Lennart Regebro指出的那样,你必须为d_dict使用特殊情况。

class Token(object):

    def __init__(self):
        super(Token,self).__setattr__('d_dict', {})

    def __getattr__(self,name):
        return self.a[name]

    def __setattr__(self,name,value):
        self.a[name] = value

您需要使用新的样式类。

答案 4 :(得分:1)

值得记住的是,__getattr__仅在对象中不存在属性时被调用,而__setattr__始终被调用。

答案 5 :(得分:0)

如果你解释它的目的,我想我们可以对你班级的整体设计说些什么。例如,

# This is a class that serves as a dictionary but also has user-defined methods
class mydict(dict): pass

# This is a class that allows setting x.attr = value or getting x.attr:
class mysetget: pass

# This is a class that allows setting x.attr = value or getting x.attr:
class mygetsethas: 
    def has(self, key):
        return key in self.__dict__

x = mygetsethas()
x.a = 5
print(x.has('a'), x.a)

我认为最后一堂课最接近你的意思,我也喜欢用语法练习并从中获得很多乐趣,但不幸的是,这不是一件好事。为什么不建议使用对象属性重新实现字典的原因:您不能使用x.3,与x.has()冲突,您必须在has('a')中添加引号等等。