Python 哪种继承方式更好?

Python 哪种继承方式更好?,python,inheritance,Python,Inheritance,这两者之间有什么区别吗: class Vehicle(): def __init__(self, x, y): self.y = y self.x = x class Car(Vehicle): def __init__(self, x, y): Vehicle.__init__(self, x, y) class Scooter(Vehicle): def __init__(self, x, y):

这两者之间有什么区别吗:

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x

class Car(Vehicle):
    def __init__(self, x, y):
        Vehicle.__init__(self, x, y)

class Scooter(Vehicle):
    def __init__(self, x, y):
         Vehicle.__init__(self,  x, y)
这是:

class Vehicle():
    def __init__(self,  x, y):
         self.y = y
         self.x = x

class Car(Vehicle):
         pass            

class Scooter(Vehicle):
         pass

因为在子类中没有
def\uuuuuuu init\uuuuu
我得到了同样的结果,我的意思是
\uuuuuu init\uuuuu
不会提供任何效果。

当您想要进行子类特定的初始化时,您需要
\uuuuuuu init\uuuuuu
方法。假设您的子类需要将另一个参数传递给构造函数,并且该参数对于该类是唯一的,在这种情况下,确实需要使用
\uuuu init\uuu
方法

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x

class Car(Vehicle):
    def __init__(self, x, y, z):
        Vehicle.__init__(self, x, y)
        self.z = z

class Scooter(Vehicle):
    def __init__(self, x, y, z):
         Vehicle.__init__(self,  x, y)
         self.z = z

当您想要执行特定于子级的初始化时,您需要
\uuuuu init\uuuu
方法。假设您的子类需要将另一个参数传递给构造函数,并且该参数对于该类是唯一的,在这种情况下,确实需要使用
\uuuu init\uuu
方法

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x

class Car(Vehicle):
    def __init__(self, x, y, z):
        Vehicle.__init__(self, x, y)
        self.z = z

class Scooter(Vehicle):
    def __init__(self, x, y, z):
         Vehicle.__init__(self,  x, y)
         self.z = z

如果您不习惯编辑超类的
\uuuu init\uuu
方法,那么调用超类的init方法是可选的

但是如果您想要编辑超类方法,您需要自定义init

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x


class Car(Vehicle):
    def __init__(self, x, y, z):
        Vehicle.__init__(self, x, y)
        self.z = z

如果您不习惯编辑超类的
\uuuu init\uuu
方法,那么调用超类的init方法是可选的

但是如果您想要编辑超类方法,您需要自定义init

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x


class Car(Vehicle):
    def __init__(self, x, y, z):
        Vehicle.__init__(self, x, y)
        self.z = z

如果您没有在子类中提供
\uuuuuuu init\uuuuu
方法,则它们将只使用在其父类(也称继承)中定义的
\uuuuuuuuu init\uuuu
方法。在前一种情况下,您正在覆盖子类的
\uuuuuu init\uuuu
方法,但您只是在调用父类的
\uuuuuuuu init\uuu
方法。因此,如果你不这样做(像后面的情况),它将是相同的。后一种情况会自动继承
\uuuu init\uuu
方法

写同样东西的其他方法是:

class Car(Vehicle): #This is the best way to do it though
   def __init__(self, x, y):
      super()__init__(x, y)


TLDR;它们是等效的。

如果在子类中不提供
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,它们将只使用父类(也称继承)中定义的
\uuuuuuuuuuuuu。在前一种情况下,您正在覆盖子类的
\uuuuuu init\uuuu
方法,但您只是在调用父类的
\uuuuuuuu init\uuu
方法。因此,如果你不这样做(像后面的情况),它将是相同的。后一种情况会自动继承
\uuuu init\uuu
方法

写同样东西的其他方法是:

class Car(Vehicle): #This is the best way to do it though
   def __init__(self, x, y):
      super()__init__(x, y)


TLDR;它们是等价的。

你不应该做它们中的任何一个。最好的方法是使用
super

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x

class Car(Vehicle):
    def __init__(self, x, y):
        super(Car, self).__init__(x, y)
        # super().__init__(x, y) # for python3

查看Raymond Hettinger(python核心贡献者)的博客文章,了解您为什么应该使用
super

这两种方法都不应该使用。最好的方法是使用
super

class Vehicle():
    def __init__(self,  x, y):
        self.y = y
        self.x = x

class Car(Vehicle):
    def __init__(self, x, y):
        super(Car, self).__init__(x, y)
        # super().__init__(x, y) # for python3

查看Raymond Hettinger(python核心贡献者)关于为什么要使用
super

的博文,我认为最好用一个例子来解释这一点

现在,以这个场景为例:

>Vehicle  ---> Car,Bike,Boat,Aeroplane,Train

>[All are vehicles right]

>Things they have in common would be (say for ex.) **Price** and **Color**
然而他们没有共同点的东西会是什么

>**Wheels**. The total number of wheels may differ.
>

> Car-4 Bike-2 Boat-0 Aeroplane-(**Not sure**) Train-(**Many I
    guess**?)
但你说对了吗?因此,当我只想拥有一个车辆对象时,我不想要(或者我无法说出车轮的数量),在这种情况下,我只能用价格和颜色进行初始化

但是,当我知道车辆的具体类型时汽车现在我可以
\uuuu init\uuuuu
使用车轮数。这就是特定于对象的初始化所起的主要作用

以上示例的完整示例代码:

class Vehicle():
    def __init__(self,  x, y):
        self.color = y
        self.price = x
    def Horn(self):
        print("Pommm...Pommmmm!!")

class Car(Vehicle):
    def __init__(self, x, y,wheel):
        Vehicle.__init__(self, x, y)
        self.wheel = "Four Wheels man: 4"

class Scooter(Vehicle):
    def __init__(self, x, y,wheel):
         Vehicle.__init__(self,  x, y)
         self.wheel = "Just Two man : 2"



VehObj = Vehicle("5000$","Black")
VehObj.Horn()
print(VehObj.color,VehObj.price)

#However note this

carObj = Car("5000$","Black",4)
print(carObj.color,carObj.price,carObj.wheel)

#Look at this

sObj = Scooter("5000$","Black",2)
print(sObj.color,sObj.price,sObj.wheel)
输出:

Pommm...Pommmmm!!
Black 5000$
Black 5000$ Four Wheels man: 4
Black 5000$ Just Two man : 2

希望这能让你清醒过来。

我想最好用一个例子来解释这一点

现在,以这个场景为例:

>Vehicle  ---> Car,Bike,Boat,Aeroplane,Train

>[All are vehicles right]

>Things they have in common would be (say for ex.) **Price** and **Color**
然而他们没有共同点的东西会是什么

>**Wheels**. The total number of wheels may differ.
>

> Car-4 Bike-2 Boat-0 Aeroplane-(**Not sure**) Train-(**Many I
    guess**?)
但你说对了吗?因此,当我只想拥有一个车辆对象时,我不想要(或者我无法说出车轮的数量),在这种情况下,我只能用价格和颜色进行初始化

但是,当我知道车辆的具体类型时汽车现在我可以
\uuuu init\uuuuu
使用车轮数。这就是特定于对象的初始化所起的主要作用

以上示例的完整示例代码:

class Vehicle():
    def __init__(self,  x, y):
        self.color = y
        self.price = x
    def Horn(self):
        print("Pommm...Pommmmm!!")

class Car(Vehicle):
    def __init__(self, x, y,wheel):
        Vehicle.__init__(self, x, y)
        self.wheel = "Four Wheels man: 4"

class Scooter(Vehicle):
    def __init__(self, x, y,wheel):
         Vehicle.__init__(self,  x, y)
         self.wheel = "Just Two man : 2"



VehObj = Vehicle("5000$","Black")
VehObj.Horn()
print(VehObj.color,VehObj.price)

#However note this

carObj = Car("5000$","Black",4)
print(carObj.color,carObj.price,carObj.wheel)

#Look at this

sObj = Scooter("5000$","Black",2)
print(sObj.color,sObj.price,sObj.wheel)
输出:

Pommm...Pommmmm!!
Black 5000$
Black 5000$ Four Wheels man: 4
Black 5000$ Just Two man : 2

希望这能帮你澄清。

第二个不是绝对继承,因为这两个类都不能从外部访问。现在你改变了密码我想没有什么区别,因为在第一个示例中,您基本上是绕过类本身的
init
,我更喜欢第一个版本,因为如果子类的
\uuuuuu init\uuuu
方法与父类没有任何不同,那么您可以扩展
\uuuuuu init\uuuuuu
-方法而不覆盖继承的代码,你的两个版本是等效的。在第一种情况下,如果调用
Car(x,y)
,则调用
Car
方法并执行
车辆。在第二种情况下,
Car
没有定义一个
\uuuuu init\uuuuu
,因此父类的
\uuuuu init\uuuuu
被调用。第二种不是绝对继承,因为这两个类都不能从外部访问。现在你改变了密码我想没有什么区别,因为在第一个示例中,您基本上是绕过类本身的
init
,我更喜欢第一个版本,因为如果子类的
\uuuuuu init\uuuu
方法与父类没有任何不同,那么您可以扩展
\uuuuuu init\uuuuuu
-方法而不覆盖继承的代码,你的两个版本是等效的。在第一种情况下,如果调用
Car(x,y)
,则调用
Car
方法并执行
车辆。在第二种情况下,
Car
没有定义一个
\uuuuu init\uuuu
,因此会调用父级的
\uuuuu init\uuuu