代码之家  ›  专栏  ›  技术社区  ›  Colin

改进了参数直接分配给成员的初始化

  •  5
  • Colin  · 技术社区  · 14 年前

    class MyClass(object):
        def __init__(self, foo, bar, foobar=1, anotherfoo=None):
            self.foo = foo
            self.bar = bar
            self.foobar = foobar
            self.anotherfoo = anotherfoo
    

    这是一个坏代码的味道吗?Python是否提供了一种更优雅的处理方法?

    class MyClass(object):
        def __init__(self, arg_dict):
            self.__dict__ = arg_dict
    
    5 回复  |  直到 14 年前
        1
  •  8
  •   Amber    14 年前

    如果他们是夸尔格人,你可以这样做:

    def __init__(self, **kwargs):
        for kw,arg in kwargs.iteritems():
            setattr(self, kw, arg)
    

    posargs有点棘手,因为你不能很好地获得命名信息。

    def __init__(self, **kwargs):
        arg_vals = {
            'param1': 'default1',
            # ...
        }
        arg_vals.update(kwargs)
        for kw,arg in arg_vals.iteritems():
            setattr(self, kw, arg)
    
        2
  •  2
  •   David Webb    14 年前

    就我个人而言,我会坚持你现在的做法,因为它不那么易碎。

    请考虑以下带有拼写错误的代码:

    myobject = MyClass(foo=1,bar=2,fobar=3)
    

    如果使用原始方法,在尝试创建对象时,您将获得以下理想行为:

    TypeError: __init__() got an unexpected keyword argument 'fobar'
    

    kwargs

    >>> myobject.fobar
    3
    

    在我看来,这似乎是很难找到的那种错误的根源。

    关键字参数 列出,以确保它只具有预期的值,但当您完成这项工作并添加默认值时,我认为它将比您原来的方法更复杂。

        3
  •  1
  •   FMc TLP    14 年前

    你可以这样做:

    def Struct(name):
        def __init__(self, **fields):
            self.__dict__.update(fields)
        cls = type(name, (object, ), {'__init__', __init__})
        return cls
    

    MyClass = Struct('MyClass')
    t = MyClass(a=1, b=2)
    

    如果你想要位置参数,那么使用这个:

    def Struct(name, fields):
        fields = fields.split()
        def __init__(self, *args, **kwargs):
            for field, value in zip(fields, args):     
                 self.__dict__[field] = value
            self.__dict__.update(kwargs)
        cls = type(name, (object, ), {'__init__': __init__})
        return cls
    

    然后像这样使用

    MyClass = Struct('MyClass', 'foo bar foobar anotherfoo')
    a = MyClass(1, 2, foobar=3, anotherfoo=4)
    

    这与 namedtuple collections 这比从本质上定义节省了更多的输入 相同的 __init__ 方法一次又一次地使用它,而不需要为了得到相同的方法而修改继承树,而不需要重新键入它。

    MyClassBase = Struct('MyClassBase', 'foo bar')
    class MyClass(MyClassBase):
        def other_method(self):
            pass
    
        4
  •  0
  •   jcao219    14 年前

    这是 好可怕 代码。

    class MyClass(object):
        def __init__(self, foo, bar, spam, eggs):
            for arg in self.__init__.func_code.co_varnames:
                setattr(self, arg, locals()[arg])
    

    然后,你可以这样做:

    myobj = MyClass(1, 0, "hello", "world")
    myletter = myobj.spam[myobj.bar]
    
        5
  •  0
  •   Seth    14 年前

    这种模式没有问题。它很容易阅读和理解(比这里的许多其他答案更容易理解)。

    如果你对输入这样的构造函数感到厌烦,那么解决方法就是让计算机为你做这件事。例如,如果您碰巧正在使用pydev进行编码,则可以按 Ctrl键 1 , A make the editor do it for you .