Python:如何引用成员变量
Python: How to refer to member variables
我一直在 Codecademy 上学习 Python,我很困惑。我不知道如何引用成员变量(我希望这就是它们的名称)。这是我写的一段代码来证明我的困惑:
class Triangle(object):
number_of_sides = 3
def __init__(self, angle1, angle2, angle3):
self.angle1 = angle1
self.angle2 = angle2
self.angle3 = angle3
def check_angles(self):
return self.angle1 + self.angle2 + self.angle3 == 180
class Equilateral(Triangle):
angle = 60
def __init__(self):
self.angle1 = self.angle
self.angle2 = self.angle
self.angle3 = self.angle
因此在等边子类中,angle1
、angle2
、angle3
不作为__init__
的参数。但是,在下面的代码中,__init__
重新初始化了 model
、color
和 mpg
。为什么是这样?它不应该像上面代码中的 Equilateral
子类一样被继承吗?我不明白为什么它们的写法不同。
class Car(object):
condition = "new"
def __init__(self, model, color, mpg):
self.model = model
self.color = color
self.mpg = mpg
def display_car(self):
print "This is a %s %s with %s MPG." %(self.color, self.model, str(self.mpg))
def drive_car(self):
self.condition = "used"
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
self.model = model
self.color = color
self.mpg = mpg
self.battery_type = battery_type
两种实现方式似乎都有些偏差。在 Python 中,一个 superclass' __init__()
是 not 自动调用的。您必须明确地这样做。
Shouldn't it just be inherited just like in the above code with the Equilateral subclass?
创建 Equilateral
的实例时,Triangle.__init__()
不会在上述实现中调用。没有自动初始化程序继承(这会违反 PEP 20:"Explicit is better than implicit")。
Equilateral
可能应该更好地阅读:
class Equilateral(Triangle):
angle = 60
def __init__(self):
super(Equilateral, self).__init__(self.angle, self.angle, self.angle)
与 ElectricCar
相同:
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
super(ElectricCar, self).__init__(model, color, mpg)
self.battery_type = battery_type
I don't understand why they were written differently.
这个问题很难回答。作者要么没有正确理解 Python 的继承是如何工作的,要么 he/she 有明确的理由不调用超级 class 初始化程序。
However, in the code below, init re-initializes model, color, and mpg. Why is this?
因为ElectricCar
的作者希望用户能够用四个参数初始化ElectricCar
。
ec = ElectricCar('xyz-500', 'blue', 0.5, 'boxy')
但是,他们应该将参数传递给基础 class' __init__
方法:
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
super(ElectricCar, self).__init__(model, color, mpg)
self.battery_type = battery_type
在EquilateralTriangle
的情况下,所有角度都相同且必须为 60 度,因此能够从用户提供的三个角度初始化这样的对象是没有意义的。
关于基础 class' __init__
的相同评论适用:
class Equilateral(Triangle):
angle = 60
def __init__(self):
super(Equilateral, self).__init__(Equilateral.angle,
Equilateral.angle,
Equilateral.angle)
另请注意,从三个角度初始化 Triangle
毫无意义,如果您谈论的是 space 三角形的内角之和为 180 度(或任何固定数字)。只传递两个角度会更有意义。
在 Python 中,classes 有点像洋葱。最外层是'instance'对象,self
。下面一层是 class 对象,self 是它的一个实例。下面的层是 class 继承自(基础 classes)的对象。
将某些内容放入 class 定义中,如 number_of_sides
中的 Triangle
,将某些内容放入 class 对象中。分配给 self
会在实例对象中放置一些东西,洋葱的不同层。
当解析像 self.angle
这样的名称时,Python 开始查看 self
层。如果在那里找不到,它会查看下面的层,依此类推。在 Equilatoral 示例中,angle
未在 self
中找到,但在 Equilatoral
class 中找到。 angle1
仅在实例变量 self
中已知,在 class 变量 Equilatoral
.
中不存在
在 Car 示例中,变量 model
、color
和 mpg
存储在 实例 中,而不是 class 本身。它们是在函数 Car.__init__
被调用时创建的,而不是通过某些魔术代码 inherited。这是设计使然,因为 Python 更喜欢显式而不是隐式行为。正如 juan 所解释的,您必须显式调用 base class 构造函数来完全初始化实例对象。
起初显式调用基本构造函数的需要似乎很繁重,但在更喜欢隐式操作的语言中(如 C++ 及其派生语言),您需要各种语法噩梦来显式覆盖隐式行为。这就是 Python 学习曲线如此平缓的原因之一。
我一直在 Codecademy 上学习 Python,我很困惑。我不知道如何引用成员变量(我希望这就是它们的名称)。这是我写的一段代码来证明我的困惑:
class Triangle(object):
number_of_sides = 3
def __init__(self, angle1, angle2, angle3):
self.angle1 = angle1
self.angle2 = angle2
self.angle3 = angle3
def check_angles(self):
return self.angle1 + self.angle2 + self.angle3 == 180
class Equilateral(Triangle):
angle = 60
def __init__(self):
self.angle1 = self.angle
self.angle2 = self.angle
self.angle3 = self.angle
因此在等边子类中,angle1
、angle2
、angle3
不作为__init__
的参数。但是,在下面的代码中,__init__
重新初始化了 model
、color
和 mpg
。为什么是这样?它不应该像上面代码中的 Equilateral
子类一样被继承吗?我不明白为什么它们的写法不同。
class Car(object):
condition = "new"
def __init__(self, model, color, mpg):
self.model = model
self.color = color
self.mpg = mpg
def display_car(self):
print "This is a %s %s with %s MPG." %(self.color, self.model, str(self.mpg))
def drive_car(self):
self.condition = "used"
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
self.model = model
self.color = color
self.mpg = mpg
self.battery_type = battery_type
两种实现方式似乎都有些偏差。在 Python 中,一个 superclass' __init__()
是 not 自动调用的。您必须明确地这样做。
Shouldn't it just be inherited just like in the above code with the Equilateral subclass?
创建 Equilateral
的实例时,Triangle.__init__()
不会在上述实现中调用。没有自动初始化程序继承(这会违反 PEP 20:"Explicit is better than implicit")。
Equilateral
可能应该更好地阅读:
class Equilateral(Triangle):
angle = 60
def __init__(self):
super(Equilateral, self).__init__(self.angle, self.angle, self.angle)
与 ElectricCar
相同:
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
super(ElectricCar, self).__init__(model, color, mpg)
self.battery_type = battery_type
I don't understand why they were written differently.
这个问题很难回答。作者要么没有正确理解 Python 的继承是如何工作的,要么 he/she 有明确的理由不调用超级 class 初始化程序。
However, in the code below, init re-initializes model, color, and mpg. Why is this?
因为ElectricCar
的作者希望用户能够用四个参数初始化ElectricCar
。
ec = ElectricCar('xyz-500', 'blue', 0.5, 'boxy')
但是,他们应该将参数传递给基础 class' __init__
方法:
class ElectricCar(Car):
def __init__(self, model, color, mpg, battery_type):
super(ElectricCar, self).__init__(model, color, mpg)
self.battery_type = battery_type
在EquilateralTriangle
的情况下,所有角度都相同且必须为 60 度,因此能够从用户提供的三个角度初始化这样的对象是没有意义的。
关于基础 class' __init__
的相同评论适用:
class Equilateral(Triangle):
angle = 60
def __init__(self):
super(Equilateral, self).__init__(Equilateral.angle,
Equilateral.angle,
Equilateral.angle)
另请注意,从三个角度初始化 Triangle
毫无意义,如果您谈论的是 space 三角形的内角之和为 180 度(或任何固定数字)。只传递两个角度会更有意义。
在 Python 中,classes 有点像洋葱。最外层是'instance'对象,self
。下面一层是 class 对象,self 是它的一个实例。下面的层是 class 继承自(基础 classes)的对象。
将某些内容放入 class 定义中,如 number_of_sides
中的 Triangle
,将某些内容放入 class 对象中。分配给 self
会在实例对象中放置一些东西,洋葱的不同层。
当解析像 self.angle
这样的名称时,Python 开始查看 self
层。如果在那里找不到,它会查看下面的层,依此类推。在 Equilatoral 示例中,angle
未在 self
中找到,但在 Equilatoral
class 中找到。 angle1
仅在实例变量 self
中已知,在 class 变量 Equilatoral
.
在 Car 示例中,变量 model
、color
和 mpg
存储在 实例 中,而不是 class 本身。它们是在函数 Car.__init__
被调用时创建的,而不是通过某些魔术代码 inherited。这是设计使然,因为 Python 更喜欢显式而不是隐式行为。正如 juan 所解释的,您必须显式调用 base class 构造函数来完全初始化实例对象。
起初显式调用基本构造函数的需要似乎很繁重,但在更喜欢隐式操作的语言中(如 C++ 及其派生语言),您需要各种语法噩梦来显式覆盖隐式行为。这就是 Python 学习曲线如此平缓的原因之一。