这里有几点你需要知道Python如何做面向对象,如果你来自Java/PHP。
在Python中,类也是非常普通的对象。这意味着类自己可以有成员变量(我们通常只是称它们为属性)。您在类块中分配的所有名称都将成为类本身的属性,而不是其任何实例的属性(包括创建方法的函数def
块;这就是Python中的所有方法)。
由于您通常有一个类和许多实例,类属性可以为Java类中的静态变量提供类似的用途,但它们并不完全相同。
在类块中分配名称从不在类的实际属性上创建属性; 只有在对象(任何对象,类或普通实例)上创建属性的方法是在其存在时分配它们。因此,Python的__init__
方法中必须存在类的实例所有变量的标准声明,并在self
上指定属性。
例如:
class Foo(object):
foo = "I am a class attribute"
def __init__(self):
self.bar = "I am an instance attribute"
如果这往往混淆了新的Python程序员是试图读从一个实例将实际工作,并找到类属性(这是方法调用如何找到foo
属性他们应该调用的函数)。所以它看起来像在类块中声明实例属性,可以用于第一次休闲游戏。但实际上只有一个属性foo
,在所有实例之间共享,如果它是可变对象并且您希望每个实例都有其自己的副本,则这可能非常糟糕。
在Python中没有访问控制,所以没有私有变量这样的事情。这是因为Python具有足够的动态性,以至于你总能绕过任何这样的限制,使它们变得毫无意义。
相反,Python程序员倾向于依靠文档和约定来确保编写客户端代码的程序员知道哪些名称是公共API的一部分,哪些是实现细节。然后,我们相信每个人都会主要遵守规则,那些不需要处理他们的代码的人就是他们不应该依赖于变化的东西。
无论如何,在任何语言中,具有微不足道的getter和setter的属性都是“公共”的;唯一可能的担忧是你可能“有一天”想要改变getter/setter的实现,以便在不改变你的接口的情况下它们不再微不足道。 Python可以通过属性来解决这个问题(基本上允许你进行方法调用,看起来像读或写属性),所以绝对没有理由拥有getter/setter方法,除非实际上有更多的事情发生。
因此,一般来说,如果期望客户端代码操纵对象的接口包括读取和写入字段,则只需记录一个普通属性可供读取和写入。如果你想清楚一个属性(或方法)纯粹是为了内部使用,通常的惯例是用一个下划线开始名称。这会强制任何使用该名称的人知道他们正在访问内部名称(因为他们必须键入前导下划线),所以您不必担心有人会“意外”使用私有属性。
关于构造,只是对待__init__
方法__construct
从PHP,它会做你所期望的(但一定要记住,Python方法明确收到self
参数;没有隐含this
)。
有这个神话,__init__
与构造函数有点不同,所以你不应该称它为一个。至于我可以告诉罪魁祸首是Dive Into Python,这相当奇怪的说:
这将是诱人的,但不正确调用这个 类的构造函数。这很诱人,因为它看起来像一个构造函数(按照约定 约定,__init__
是为该类定义的第一个方法),行为 就像一个(它是在该类的新创建的 实例中执行的第一段代码),甚至听起来像一个(“初始化”当然 建议一个构造函数性质)。不正确,因为对象具有 的时间已被调用__init__
被调用,并且您的 已具有对该类的新实例的有效引用。
但“对象已经由时间__init__
构造被调用,并且你已经有了类的新实例的有效引用”精确表征的构造是如何传统的工作,所以我不知道什么时候作者正试图在那里。
(该出现采取官方行是MyClass(arg1, arg2)
是构造表达; __init__
和__new__
都描述为接收被赋予给构造表达式的所有参数,并且__init__
明确地称为构造这两个术语都很少使用的文档;他们只是说__init__
最重要的时间)
所以我劝你忽略人谁试图告诉你,__init__
不是构造函数。你将通过类比构造函数来理解__init__
,而不是试图理解他们在构造函数和__init__
之间做出的关键区别。
把所有在一起,你的PHP类的成语翻译将是简单如下:
class MyClass(object):
def __init__(self, myMember):
self.myMember = myMember
好吧,'__init__'是一个构造函数,就像PHP的'__construct'是一个构造函数一样。无论您是否同意这个术语,'__new__'是其他语言称为工厂的东西(有些语言支持可以方便地调用它),并且它比其他语言称为构造函数的功能严格得多(可以返回不同或已有的对象) 。所以,OP:只需使用'__init__',句号。 – delnan
在我有经验的每种* OO语言中,您编写的用于初始化对象并称为构造函数的代码块将在已存在的对象上调用。因此,如果Python和PHP构造函数“不是真正的构造函数”,那么Java或C++构造函数都不是。 – Ben
为什么你要将'__new__'作为静态方法?我倾向于认为它是一个类方法,因为第一个参数是一个类... – mgilson