Python 关于子类化的问题
我整个上午都在读关于子类化的书,但仍然有一些问题。假设我们有以下类别的汽车:Python 关于子类化的问题,python,python-3.x,Python,Python 3.x,我整个上午都在读关于子类化的书,但仍然有一些问题。假设我们有以下类别的汽车: class Car(): doors=4 color='red' def __init__(self,gas,miles): self.gas=gas self.miles=miles @property #responsible for handing back the value of the variable gas def gas(self
class Car():
doors=4
color='red'
def __init__(self,gas,miles):
self.gas=gas
self.miles=miles
@property #responsible for handing back the value of the variable gas
def gas(self):
return self._gas
@gas.setter #responsible for setting the value of the variable gas
def gas(self,x):
if x<0:
raise ValueError('Gas cannot be negative')
self._gas=x
这是行不通的。有几个问题:
super()
super()。\uuuu init\uuuu(汽油,英里)
回答您的问题: 通过将
Car
子类化为ElectricCar
,您可以创建一个名为“ElectricCar”的新类,该类除了添加到ElectricCar
中的内容外,还包含Car类的所有属性、属性和功能。电动汽车是一辆汽车和其他东西。通过调用super()。\uuuuu init\uuuuu
在这种情况下,您正在调用类的父类上的构造函数(函数)。出现错误是因为此函数需要两个参数:gas
和miles
,但您只提供一个。调用任何方法时,必须提供该方法所需的所有参数
在您的情况下,您的电动汽车
不需要汽油
,因为它代表电动汽车。但是,在Python中,您没有选择说,“我想从Car
继承这个,但不是那个”。因此,您的架构存在问题,因为您假设汽车的基本情况是汽油车。因此,您应该从Car
中删除gas
属性,并创建一个封装该信息的GasolineCar
类 要回答您的问题:
通过将Car
子类化为ElectricCar
,您可以创建一个名为“ElectricCar”的新类,该类除了添加到ElectricCar
中的内容外,还包含Car类的所有属性、属性和功能。电动汽车是一辆汽车和其他东西。通过调用super()。\uuuuu init\uuuuu
在这种情况下,您正在调用类的父类上的构造函数(函数)。出现错误是因为此函数需要两个参数:gas
和miles
,但您只提供一个。调用任何方法时,必须提供该方法所需的所有参数
在您的情况下,您的电动汽车
不需要汽油
,因为它代表电动汽车。但是,在Python中,您没有选择说,“我想从Car
继承这个,但不是那个”。因此,您的架构存在问题,因为您假设汽车的基本情况是汽油车。因此,您应该从Car
中删除gas
属性,并创建一个封装该信息的GasolineCar
类 我们来举一个非常简单的例子:
class Foo:
ca1="a class attribute in Foo"
def __init__(self, dv1, dv2="a default value"):
self.ia="an instance attribute in Foo"
self.dv1=dv1
self.dv2=dv2
class Bar(Foo):
ca2="a class attribute in Bar"
def __init__(self, dv="new default from Bar"):
self.ia="an instance attribute in Bar"
super().__init__("from Bar 1", dv)
Bar
的任何实例都将继承Foo
所有属性,而不是专门添加或覆盖的属性
为了演示,可以使用来显示每个实例的属性。(我过滤掉了内部方法和属性,只关注用户属性):
您可以在Foo
的实例中看到类和实例变量
现在看一个Bar
的实例:
>>> [a for a in inspect.getmembers(Bar(), lambda at: not(inspect.isroutine(at))) if not(a[0].startswith('__'))]
[('ca1', 'a class attribute in Foo'),
('ca2', 'a class attribute in Bar'),
('dv1', 'from Bar 1'),
('dv2', 'new default from Bar'),
('ia', 'an instance attribute in Foo')]
如果将super
从Bar
中的\uuuuu init\uuuu
中删除,则Foo
中的\uuuu init\uuuu
将永远不会被调用。结果是可见的,与Foo
中的\uuuuu init\uuuu
相关的隐式代码(如实例值的赋值)未完成:
class Bar(Foo):
ca2="a class attribute in Bar"
def __init__(self, dv="new default from Bar"):
self.ia="an instance attribute in Bar"
不同之处在于,Foo
中的实例属性不会作为属性添加到Bar
的实例中(以及添加到Foo
的实例中的任何其他特定添加):
我们来举一个非常简单的例子:
class Foo:
ca1="a class attribute in Foo"
def __init__(self, dv1, dv2="a default value"):
self.ia="an instance attribute in Foo"
self.dv1=dv1
self.dv2=dv2
class Bar(Foo):
ca2="a class attribute in Bar"
def __init__(self, dv="new default from Bar"):
self.ia="an instance attribute in Bar"
super().__init__("from Bar 1", dv)
Bar
的任何实例都将继承Foo
所有属性,而不是专门添加或覆盖的属性
为了演示,可以使用来显示每个实例的属性。(我过滤掉了内部方法和属性,只关注用户属性):
您可以在Foo
的实例中看到类和实例变量
现在看一个Bar
的实例:
>>> [a for a in inspect.getmembers(Bar(), lambda at: not(inspect.isroutine(at))) if not(a[0].startswith('__'))]
[('ca1', 'a class attribute in Foo'),
('ca2', 'a class attribute in Bar'),
('dv1', 'from Bar 1'),
('dv2', 'new default from Bar'),
('ia', 'an instance attribute in Foo')]
如果将super
从Bar
中的\uuuuu init\uuuu
中删除,则Foo
中的\uuuu init\uuuu
将永远不会被调用。结果是可见的,与Foo
中的\uuuuu init\uuuu
相关的隐式代码(如实例值的赋值)未完成:
class Bar(Foo):
ca2="a class attribute in Bar"
def __init__(self, dv="new default from Bar"):
self.ia="an instance attribute in Bar"
不同之处在于,Foo
中的实例属性不会作为属性添加到Bar
的实例中(以及添加到Foo
的实例中的任何其他特定添加):
看看类属性、实例属性和默认值之间的区别。您可以继承属于该类的所有属性。这包括可以设置实例属性的方法,如init,除非它被重写。是的,当您调用super()时,必须向它传递正确的参数。所有继承本质上都是在方法解析期间检查基类。因此,当您执行myobject.some_attribute
时,首先检查实例名称空间的some_attribute
,然后检查类名称空间,然后按方法解析顺序检查所有类名称空间。这种继承似乎是错误的。Car
类应该定义每单位“燃料”的最大速度、加速度、行驶距离(不限制wha)