代码之家  ›  专栏  ›  技术社区  ›  Humphrey Bogart

python 3对象构造:哪一种是最常用的pythonic/被接受的方式?

  •  8
  • Humphrey Bogart  · 技术社区  · 15 年前

    在Java中有一个非常冗长而严格的背景,我发现能够改变Python对象的能力,以便给它们提供除了那些构造函数之外的字段,它们确实是“丑陋”的。

    试着让自己习惯于一种蟒蛇式的思维方式, 我想知道我应该如何让我的物体被建造 .

    我的直觉是必须 施工时经过现场 ,例如:

    def __init__(self, foo, bar, baz=None):
        self.foo = foo
        self.bar = bar
        self.baz = baz
    

    但是,这可能会变得过于冗长,并与许多要传递的字段混淆。为了克服这一点,我认为最好的方法是 将一个字典传递给构造函数,从中提取字段 以下内容:

    def __init__(self, field_map):
        self.foo = field_map["foo"]
        self.bar = field_map["bar"]
        self.baz = field_map["baz"] if baz in field_map else None
    

    我能想到的另一个机制是 在其他地方添加字段 例如:

    class Blah(object):
    
        def __init__(self):
            pass
    
    ...
    
    blah = Blah()
    blah.foo = var1
    

    但感觉如此 方式 我穿太宽松了。

    (我想我头脑中的问题是我如何处理 界面 在蟒蛇……

    所以,要重申一个问题:我应该如何在Python中构造我的对象?有公认的惯例吗?

    2 回复  |  直到 15 年前
        1
  •  9
  •   Otto Allmendinger    15 年前

    你描述的第一个很常见。有些人用较短的

    class Foo:
       def __init__(self, foo, bar):
           self.foo, self.bar = foo, bar
    

    第二种方法并不常见,但类似的版本是:

    class Thing:
       def __init__(self, **kwargs):
           self.something = kwargs['something']
           #..
    

    它允许创建类似

    t = Thing(something=1)
    

    这可以进一步修改为

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

    允许

    t = Thing(a=1, b=2, c=3)
    print t.a, t.b, t.c # prints 1, 2, 3
    

    正如Debilski在注释中指出的,最后一个方法有点不安全,您可以添加一个接受参数列表,如下所示:

    class Thing:
        keywords = 'foo', 'bar', 'snafu', 'fnord'
        def __init__(self, **kwargs):
            for kw in self.keywords:
                setattr(self, kw, kwargs[kw])
    

    有许多变化,没有共同的标准,我知道。

        2
  •  3
  •   Debilski    15 年前

    我没见过你 field_map 在现实生活中。我认为只有当你使用 菲尔德地图 在代码中的其他地方。

    关于你的第三个例子:即使你不需要分配给他们(除了 None )通常在 __init__ 方法,这样您就可以轻松查看对象的属性。

    所以下面的内容比简单的 爱因斯坦 方法(你也会得到更高的 皮林特 得分):

    class Blah(object):
        def __init__(self):
            self.foo = None
            self.bar = None
    
    blah = Blah()
    blah.foo = var1
    

    这种方法的问题是,在初始化之后,对象可能处于未定义好的状态,因为您尚未定义所有对象的属性。这取决于对象的逻辑(代码和含义中的逻辑)以及对象的工作方式。如果是这样的话,我建议你 这样做。如果你的目标依赖 foo bar 为了有意义的定义,你 应该 把它们放进你的 爱因斯坦 方法。

    但是,如果属性 酒吧 不是强制性的,以后您可以自由定义它们。

    如果参数列表的可读性是您的一个问题:请使用关键字参数。