3

我有一个包含许多具有默认值的实例变量的类,可以选择在实例化中覆盖它(注意:没有可变的默认参数)。

由于self.x = x多次编写等非常多余,因此我以编程方式初始化变量。

为了说明,考虑这个例子(为了简洁起见,它只有 5 个实例变量和省略了任何方法):

例子:

# The "painful" way
class A:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e

# The "lazy" way
class B:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
        self.__dict__.update({k: v for k, v in locals().items() if k!='self'})

# The "better lazy" way suggested
class C:
    def __init__(self, a, b=2, c=3, d=4.5, e=5):
            for k, v in locals().items():
                if k != 'self':
                    setattr(self, k, v)

x = A(1, c=7)
y = B(1, c=7)
z = C(1, c=7)

print(x.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}
print(y.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}
print(z.__dict__)  # {'d': 4.5, 'c': 7, 'a': 1, 'b': 2, 'e': 5}

因此,为了让我的生活更轻松,我使用 B 类中显示的习语,它产生与 A 相同的结果。

这是不好的做法吗?有什么陷阱吗?

附录: 使用这个习语的另一个原因是为了节省一些空间——我打算在MicroPython中使用它。无论出于何种原因 因为当地人在那里的工作方式不同,所以只有 A 类中显示的方式在其中有效。

4

2 回答 2

3

我实际上建议使用class A. 你所拥有的是重复代码,而不是冗余代码,重复并不总是坏事。您只需要编写__init__一次,并且为每个实例变量保留一个赋值对于您的类期望的实例变量是很好的文档(明确且清晰)。

但是,要记住的一件事是,可以初始化为不同参数的变量过多可能表明您的类需要重新设计。将某些单独的参数分组到单独的列表、字典甚至其他类中是否更有意义?

于 2016-11-30T23:38:08.243 回答
1

尝试一种更 Pythonic 的方法:

class C:
  def __init__(self,a,b=2,c=3,d=4.5,e=5):
    for k,v in locals().iteritems():
      setattr(self,k,v)
c = C(1)
print c.a, c.b
1 2

这种方法可能会长一两行,但行的长度更短,你的意图也不那么复杂。此外,任何可能尝试重用您的代码的人都将能够按预期访问您的对象的属性。

希望这可以帮助。

编辑:使用 kwargs bc 删除了第二种方法,它没有解决默认变量要求。

这里重要的一点是,如果像示例 B 类所示的那样完成,您的代码用户将无法按预期访问您的对象的属性。

于 2016-11-30T23:28:15.860 回答