如何避免意外创建类属性

时间:2018-12-29 06:21:52

标签: python-3.x

我知道的座右铭是“我们都同意这里的成年人。”

但是这是我花了一天的时间的问题。我通过了具有100多个属性的课程。我已指定其中一个称为“ run_count”。前端可以输入run_count。

不知何故,前端/后端软件包人们决定将其称为“ run_iterations”。

所以,我的问题是我正在编写单元测试软件,而我做到了:

passed_parameters.run_count = 100
result = do_the_thing(passed_parameters)
assert result == 99.75

现在,问题当然在于,Python愿意让我设置这个名为“ run_count”的“新”属性。但是,在将代码深入10层之后,我发现函数“ do_the_thing”(显然)从不看“ run_count”,而是使用“ passed_pa​​ramaters.run_iterations”。

当您天真地假定您知道属性名称(或dict键)而无意间创建了一个新的属性时,是否有一些简单的方法来避免允许您自己在类中创建新属性或在词典中创建新条目永远不会被关注的条目?

在理想的世界中,无论动态如何,Python都将允许您“锁定”对象和对象或实例。然后,尝试为不存在的属性设置新值将引发属性错误,让您知道您正在尝试更改不存在的内容,而不是让您创建一个永远不会使用的新属性。

1 个答案:

答案 0 :(得分:4)

使用__setattr__,并检查属性是否存在,否则引发错误。如果这样做,在__init__中定义这些属性时会收到错误消息,因此您必须解决这种情况。我找到了四种方法。首先,在类中定义那些属性,这样,当您尝试设置它们的初始值时,就已经定义了它们。其次,直接致电object.__setattr__。第三,向__setattr__添加第四个布尔参数,指示是否绕过检查。第四,将先前的布尔值标志定义为全班级,将其设置为True,初始化字段并将标志设置回False。这是代码:

代码

class A:
  f = 90
  a = None

  bypass_check = False

  def __init__(self, a, b, c, d1, d2, d3, d4):
    # 1st workaround
    self.a = a

    # 2nd workaround
    object.__setattr__(self, 'b', b)

    # 3rd workaround
    self.__setattr__('c', c, True)

    # 4th workaround
    self.bypass_check = True 
    self.d1 = d1
    self.d2 = d2
    self.d3 = d3
    self.d4 = d4
    self.bypass_check = False

  def __setattr__(self, attr, value, bypass=False):
    if bypass or self.bypass_check or hasattr(self, attr):
      object.__setattr__(self, attr, value)
    else:
      # Throw some error
      print('Attribute %s not found' % attr)

a = A(1, 2, 3, 4, 5, 6, 7)
a.f = 100
a.d1 = -1
a.g = 200
print(a.f, a.a, a.d1, a.d4)

输出

Attribute g not found
100 1 -1 7