Python 3对象构造:哪个是最Pythonic /可接受的方式?

Hum*_*art 8 python conventions python-3.x

在Java中有一个非常冗长和严格的背景,我发现能够改变Python对象,以便为它们提供除了提供给构造函数之外的字段真的"丑陋".

试图让自己习惯于Pythonic的思维方式,我想知道我应该如何构建我的对象.

我的直觉是必须在施工时传递字段,例如:

def __init__(self, foo, bar, baz=None):
    self.foo = foo
    self.bar = bar
    self.baz = baz
Run Code Online (Sandbox Code Playgroud)

但是,这可能会变得过于冗长和令人困惑,许多领域都要通过.为了克服这个问题,我假设最好的方法是将一个字典传递给构造函数,从中提取字段:

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
Run Code Online (Sandbox Code Playgroud)

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

class Blah(object):

    def __init__(self):
        pass

...

blah = Blah()
blah.foo = var1
Run Code Online (Sandbox Code Playgroud)

但随着那种感觉这样太松了我.

(我想我脑子里的问题是我如何处理Python中的接口 ......)

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

Ott*_*ger 9

你描述的第一个很常见.有些使用较短的

class Foo:
   def __init__(self, foo, bar):
       self.foo, self.bar = foo, bar
Run Code Online (Sandbox Code Playgroud)

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

class Thing:
   def __init__(self, **kwargs):
       self.something = kwargs['something']
       #..
Run Code Online (Sandbox Code Playgroud)

它允许创建像

t = Thing(something=1)
Run Code Online (Sandbox Code Playgroud)

这可以进一步修改为

class Thing:
   def __init__(self, **kwargs):
       self.__dict__.update(kwargs)
Run Code Online (Sandbox Code Playgroud)

允许

t = Thing(a=1, b=2, c=3)
print t.a, t.b, t.c # prints 1, 2, 3
Run Code Online (Sandbox Code Playgroud)

正如Debilski在评论中指出的那样,最后一种方法有点不安全,你可以添加一个接受的参数列表,如下所示:

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

有很多变化,我没有共同的标准.