Python 3 对象构造:哪种是最Pythonic / 被接受的方式?
我有 Java 背景,Java 非常冗长和严格,我发现改变 Python 对象的能力,为它们提供除呈现给构造函数的字段之外的字段,这真的“丑陋”。
为了让自己习惯 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
我能想到的另一种机制是将字段添加到其他地方 em>,例如:
class Blah(object):
def __init__(self):
pass
...
blah = Blah()
blah.foo = var1
但这对我来说感觉方式太松了。
(我想我脑子里的问题是如何在 Python 中处理接口...)
所以,重申一下这个问题:我应该如何在 Python 中构造我的对象?有公认的约定吗?
Having a background in Java, which is very verbose and strict, I find the ability to mutate Python objects as to give them with fields other than those presented to the constructor really "ugly".
Trying to accustom myself to a Pythonic way of thinking, I'm wondering how I should allow my objects to be constructed.
My instinct is to have to pass the fields at construction time, such as:
def __init__(self, foo, bar, baz=None):
self.foo = foo
self.bar = bar
self.baz = baz
But that can become overly verbose and confusing with many fields to pass. To overcome this I assume the best method is to pass one dictionary to the constructor, from which the fields are extracted:
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
The other mechanism I can think of is to have the fields added elsewhere, such as:
class Blah(object):
def __init__(self):
pass
...
blah = Blah()
blah.foo = var1
But as that feels way too loose for me.
(I suppose the issue in my head is how I deal with interfaces in Python...)
So, to reiterate the question: How I should construct my objects in Python? Is there an accepted convention?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你描述的第一个很常见。有些人使用较短的
第二种方法并不常见,但类似的版本是这样的:
它允许创建像这样的对象
这可以进一步修改为
允许
正如Debilski在评论中指出的那样,最后一种方法有点不安全,你可以添加接受的参数列表,如下所示:
有很多变体,据我所知没有通用标准。
The first you describe is very common. Some use the shorter
Your second approach isn't common, but a similar version is this:
which allows to create objects like
This can be further modified to
allowing
As Debilski points out in the comments, the last method is a bit unsafe, you can add a list of accepted parameters like this:
There are many variations, there is no common standard that I am aware of.
我在现实生活中没见过很多
field_map
。我认为只有当您也在代码中的其他位置使用field_map
时,这才有意义。关于您的第三个示例:即使您不需要分配给它们(
None
除外),但通常的做法是在__init__
方法中显式声明属性,因此您将很容易地看到您的对象具有哪些属性。因此,以下方法比简单地使用空的 __init__ 方法要好(您还将获得更高的 pylint 分数):
这种方法的问题是,您的对象初始化后可能处于未明确定义的状态,因为您尚未定义对象的所有属性。这取决于对象的逻辑(代码和含义中的逻辑)以及对象的工作方式。但如果是这种情况,我建议您不要这样做。如果您的对象依赖于
foo
和bar
进行有意义的定义,您应该将它们真正放入您的__init__
中方法。但是,如果属性
foo
和bar
不是必需的,那么您可以在以后自由定义它们。如果参数列表的可读性对您来说是个问题:使用关键字参数。
I’ve not seen many of your
field_map
s in real life. I think that would only make sense if you were to use thefield_map
at some other place in your code as well.Concerning your third example: Even though you don’t need to assign to them (other than
None
), it is common practice to explicitly declare attributes in the__init__
method, so you’ll easily see what properties your object has.So the following is better than simply having an empty
__init__
method (you’ll also get a higher pylint score for that):The problem with this approach is, that your object might be in a not well-defined state after initialisation, because you have not yet defined all of your object’s properties. This depends on your object’s logic (logic in code and in meaning) and how your object works. If it is the case however, I’d advise you not to do it this way. If your object relies on
foo
andbar
to be meaningfully defined, you should really put them inside of your__init__
method.If, however, the properties
foo
andbar
are not mandatory, you’re free to define them afterwards.If readability of the argument lists is an issue for you: Use keyword arguments.