是自我.__ dict __.更新(**kwargs)好或坏的风格?

Ale*_*ary 41 python oop dictionary

在Python中,假设我有一些继承自Shape的类Circle.形状需要x坐标和y坐标,此外,圆需要半径.我希望能够通过做类似的事情来初始化Circle,

c = Circle(x=1., y=5., r=3.)
Run Code Online (Sandbox Code Playgroud)

Circle继承自shape,因此我需要使用命名参数__init__,因为不同的类需要不同的构造函数.我可以手动设置x,y和r.

class Shape(object):
    def __init__(self, **kwargs):
        self.x = kwargs['x']
        self.y = kwargs['y']

class Circle(Shape):
    def __init__(self, **kwargs):
        super(Circle, self).__init__(**kwargs)
        self.r = kwargs['r']
Run Code Online (Sandbox Code Playgroud)

或者,我可以自动使用我的圆圈属性 self.__dict__.update(kwargs)

class Shape(object):
    def __init__(self, **kwargs):
        self.__dict__.update(**kwargs)

class Circle(Shape):
    def __init__(self, **kwargs):
        super(Circle, self).__init__(**kwargs)
Run Code Online (Sandbox Code Playgroud)

这样做的好处是代码更少,我不需要维护样板self.foo = kwargs['foo'].缺点是Circle不需要哪些参数.这被认为是作弊还是这种好风格(只要Circle的界面有详细记录)?


谢谢大家,感谢您的深思熟虑.在self.__dict__.update(**kwargs)我试验组织我的代码时,hack对我很有用,但我会确保通过明确地正确传递参数并在生产代码中进行明确的错误检查来替换它.

Rom*_*huk 25

class Shape(object):
    def __init__(self, x=None, y=None):
        self.x = x
        self.y = y

class Circle(Shape):
    def __init__(self, r=None, **kwargs):
        super(Circle, self).__init__(**kwargs)
        self.r = r
Run Code Online (Sandbox Code Playgroud)

就是这样.**kwargs当你不真正需要它们时不要使用.

这被认为是作弊还是这种好风格(只要Circle的界面有详细记录)?

如果您可以选择编写简单易懂的代码和令人头疼的代码+漂亮的文档字符串,那么您实际上没有任何选择,只需编写简单的自编代码:)

  • 对于此解决方案,请注意,此继承链中的所有类都无法访问以这种方式从(**kwargs)中剥离的关键字值(在子类中).例如,Shape不能定义`r`参数并期望得到它,而不修改Circle的`__init__`方法. (2认同)

And*_*ark 17

我会说第一种方法绝对是可取的,因为显式优于隐式.

考虑如果你在初始化一个圆圈时弄错了会发生什么,比如说Circle(x=1., y=5., rr=3.).您希望立即看到此错误,这不会发生__dict__.update(kwargs).


Sim*_*ser 10

如果您想自动分配,我建议采用以下方法:

def __init__(self, **kwargs):
    for key, value in kwargs.iteritems():
        setattr(self, key, value)
Run Code Online (Sandbox Code Playgroud)

就风格而言,它介于两者之间,明确地写它并自己使用它self.__dict__.

  • 这将具有使用描述符的优点.直接与`__dict__`一起工作仅仅是因为这个原因. (5认同)
  • 你能帮我理解为什么这对描述符有效吗? (3认同)
  • 在阅读https://docs.python.org/3/howto/descriptor.html之后,我的理解是Chris Morgan(~2)正在推广Simeon的答案,因为它可以更好地使用基于您的课程的课程乘坐默认的get/set方法,从而成为数据描述符.使用setattr将与它们的over-ride兼容,而直接使用__dict__将绕过任何此类覆盖. (3认同)