2015-12-21 89 views
1

如何检查用户的属性是否已由用户设置?目前,我有一个类如何检查属性是否具有在__init__中定义的默认值

class foo: 
    def __init__(self): 
     self.bar = 'baz' 

后来我想检查,如果用户设定的bar值与否,即具有类似

my_foo = foo() 
my_foo.bar = 'mybaz' 

,所以我想知道如果第二上面的行已经被调用或不被调用(如果没有的话,会发出警告)。我有两个解决方案,但我不喜欢它们中的:

  1. 检查my_foo.bar等于默认值。但它可能是用户设置my_foo.bar为相同的值,然后我不想发出警告。

  2. 请勿在__init__中设置默认值,但仅在使用时才有效。然后可以使用getattr()进行检查,并使用setattr()进行设置。

我敢肯定,有一种优雅的pythonic方式来做到这一点,我没有想到。

+0

会阻止直接分配给这些属性就够了吗?即分配完成后立即抛出异常?请解释你想要检查的方式 – Pynchia

回答

6

使用@property装饰构建getter和setter,以及使二传手告诉你,当用户更改属性,例如下面

class Foo: 

    def __init__(self): 
     self._x_was_modified = False 
     self._x = None 

    @property 
    def x(self): 
     return self._x 

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

foo = Foo() 
print('x was modified by user: {}'.format(foo._x_was_modified)) 
foo.x = 42 
print('x was modified by user: {}'.format(foo._x_was_modified)) 

这将输出:

x was modified by user: False 
x was modified by user: True 
2

另一种解决方案再次涉及使用flag是通过玩弄__setattr__方法完成的:

class foo: 
    def __init__(self): 
     self._altered = -1 
     self.bar = 'baz' 

    def __setattr__(self, attrname, val): 
     if attrname is 'bar': 
      self._altered += 1 
     super.__setattr__(self, attrname, val) 
     # if you heard super is evil and you feel 
     # funny using it in your code instead use: 
     # object.__setattr__(self, attrname, val) 

如果有人再套这个变量的self._altered值将是积极的,结果评估,以True(记住,第一个访问是在__init__初始化和增量_altered期间进行一次)。

在此之后,你可以使窗体的一个很好的直观检查:

f = foo() 
f.bar = "booz" # now f._altered == 1 

if f._altered: raise MyAlcoholicException 

和完成。只是另一种做几乎完全相同的事情的方式。

+0

https://docs.python.org/2/library/functions.html#super super是一种方法,应该这样调用,解决方法也很麻烦,不建议生产使用IMO。 – brunsgaard

+0

OP使用'Py3'中使用的新样式类,所以我使用了'super',另外我提供了更多的一般委托给'object'。如果这件事很麻烦或者没有争议,那么评论就不是这次辩论的地方。无论哪种方式,在提供替代解决方案方面都没有任何坏处我接受你的downvote任一方式:) –

相关问题