2012-01-13 166 views
23

我是刚刚开始学习Python的Java人。就拿这个例子:使用__init__继承Python中的属性

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 

class Teenager(Person): 
    def __init__(self, name, phone, website): 
     self.name=name 
     self.phone=phone 
     self.website=website 

我敢肯定有很多冗余代码(我知道在Java中,有一段代码位大量裁员以上)。

哪些部分对于哪些属性已经从父类继承而言是多余的?

回答

29

当为python中的类编写__init__函数时,您应该始终调用其超类的__init__函数。我们可以用它来直接传递相关属性的超类,所以你的代码应该是这样的:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def __init__(self, name, phone, website): 
     Person.__init__(self, name, phone) 
     self.website=website 

正如其他人所指出的那样,你可以用

更换线

Person.__init__(self, name, phone) 

super(Teenager, self).__init__(name, phone) 

和代码将做同样的事情。这是因为python instance.method(args)只是Class.method(instance, args)的简写。如果你想使用super,你需要确保你指定了object作为Person的基类,就像我在我的代码中所做的那样。

python documentation有关于如何使用关键字super的更多信息。在这种情况下,重要的是,它告诉Python来寻找方法__init__self超类,是不是Teenager

+2

请注意,如果您使用的是Python 2.x,则必须将'object'明确列出为'Person'的基类以便使用'super()'。否则,你必须使用'Person .__ init__'形式。 – chepner 2012-01-13 17:17:58

+0

@chepner你能提供一个参考吗?我找不到一个。 – murgatroid99 2012-01-13 17:19:08

+0

http://docs.python.org/library/functions.html#super表示super()仅支持新样式类,它在Python 2.x中是那些从'object'继承的类。 – chepner 2012-01-13 17:21:59

5

Python中的属性,当他们在构造和父类的构造函数定义是不能继承的不叫,除非你手动做这一切:

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     Person.__init__(self, name, phone) # Call parent class constructor. 
     self.website=website 

更多在这里:http://docs.python.org/tutorial/classes.html#inheritance

1

__init__,不像Java的构造,不会自动要求继承层次结构中的每个类 - 你需要ŧ o自己动手。

此外,您的所有对象层次结构都应根据object(特殊情况除外)。

您的代码应阅读:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     super(Teenager, self).__init__(name, phone) 
     self.website=website 

super它的第二个参数(self),这将调用下一个函数的函数列表来调用每个名称(以下简称“方法解析顺序创建一个委托“)。这与调用超类方法并不完全相同,就像在Java中发生的那样。

你也可以写super(type(self), self).__init__(name, phone),但如果你从这个类继承进一步,type(self)可能不是Teenager,你可以有一个无限递归。这是事实的一个实际结果,即您正在使用具有差异MRO的委托对象,而不是直接调用超类构造函数。

11

稍微清洁的方式,我喜欢这样做:

class Teenager(Person): 
     def __init__(self, *args, **kwargs): 
      self.website=kwargs.pop('website') 
      super(Teenager, self).__init__(*args, **kwargs) 

它没有多大的差别在这种情况下,但是当你有一个__init__一吨的参数,它使生活更轻松。

+0

Upvoted使用* args和** kwargs(...在很多参数的情况下是有效的)。 – 2015-11-23 17:53:23