为什么这个继承结构是这样构建的呢?
Why is this inheritance structure built like this?
几天来我一直在努力理解这段代码的细节:
class Rectangle:
def __init__(self, length, width, **kwargs):
self.length = length
self.width = width
super().__init__(**kwargs)
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * self.length + 2 * self.width
# Square inherits from Rectangle:
class Square(Rectangle):
def __init__(self, length, **kwargs):
super().__init__(length=length, width=length, **kwargs)
# Triangle doesn't inherit from any class:
class Triangle:
def __init__(self, base, height, **kwargs):
self.base = base
self.height = height
super().__init__(**kwargs)
def tri_area(self):
return 0.5 * self.base * self.height
# Pyramid inherits from square and triangle:
class Pyramid(Square, Triangle):
def __init__(self, base, slant_height, **kwargs):
self.base = base
self.slant_height = slant_height
# Adding attributes to kwargs dictionary
kwargs["height"] = slant_height
kwargs["length"] = base
super().__init__( base=base, **kwargs)
def area(self):
base_area = super().area()
perimeter = super().perimeter()
return 0.5 * perimeter * self.slant_height + base_area
def area_2(self):
base_area = super().area()
triangle_area = super().tri_area()
return triangle_area * 4 + base_area
继承树是这样的:
Rectangle
\
Square Triangle
\ /
Pyramid
Pyramid
class 的 MRO:
(__main__.Pyramid,
__main__.Square,
__main__.Rectangle,
__main__.Triangle,
object)
我了解代码背后的总体思路,以及如何使用 super().__init__
将可变关键字参数字典传递给使用 **kwargs
的 superclass。我遇到问题的详细信息是:
- 为什么我们在
Pyramid
class 中使用 base=base
而 superclass (Square
) 需要 length
争论?
- 当我只输入
super().__init__(base, **kwargs)
而不是 base=base
时,为什么会报错 init() got参数 'length', 的多个值是因为上面指定的 kwargs["length"]
吗?如果是这样,base=base 是如何解决的?
- 为什么我们在 Rectangle 中没有 superclass 而有
super().__init__(**kwargs)
?我的猜测可能是将 kwargs 传递给内置的 object
基 class 所以 Triangle
可以继承它?但我不确定。
- 为什么
Triangle
也会调用基地 class?这似乎是多余的(即使从 Triangle 中删除 super().__init__(**kwargs)
也不会改变任何东西)。
好问题!
因为 Square.__init__
接受 **kwargs
我们实际上可以传递我们想要的任何东西而不会得到 unexpected keyword argument
错误1.这稍后会变得很方便。它(and/or 它的超类的 __init__
方法)不使用的任何关键字参数都将在 MRO 中向上传播,直到我们到达 object
.
1通常。在这种情况下,(不必要的)调用
super().__init__(**kwargs)
in Triangle.__init__
打破了这种行为。
由于kwargs
的扩展,在Pyramid.__init__
中调用super().__init__(base, **kwargs)
时,Square.__init__
实际上是用(2, height=3, length=2)
调用的。由于 Square.__init__
的参数称为 length
,您会收到有关 length
.
的多个值的错误
没错。此外,因为还没有任何东西“消耗” base
关键字参数,所以 Triangle.__init__
将接收它。
也对。绝对没有必要在 Triangle.__init__
中调用 super().__init__(**kwargs)
,尤其是到那时 kwargs
是一个空字典(它包含的所有关键字参数都已经被消耗)。
几天来我一直在努力理解这段代码的细节:
class Rectangle:
def __init__(self, length, width, **kwargs):
self.length = length
self.width = width
super().__init__(**kwargs)
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * self.length + 2 * self.width
# Square inherits from Rectangle:
class Square(Rectangle):
def __init__(self, length, **kwargs):
super().__init__(length=length, width=length, **kwargs)
# Triangle doesn't inherit from any class:
class Triangle:
def __init__(self, base, height, **kwargs):
self.base = base
self.height = height
super().__init__(**kwargs)
def tri_area(self):
return 0.5 * self.base * self.height
# Pyramid inherits from square and triangle:
class Pyramid(Square, Triangle):
def __init__(self, base, slant_height, **kwargs):
self.base = base
self.slant_height = slant_height
# Adding attributes to kwargs dictionary
kwargs["height"] = slant_height
kwargs["length"] = base
super().__init__( base=base, **kwargs)
def area(self):
base_area = super().area()
perimeter = super().perimeter()
return 0.5 * perimeter * self.slant_height + base_area
def area_2(self):
base_area = super().area()
triangle_area = super().tri_area()
return triangle_area * 4 + base_area
继承树是这样的:
Rectangle
\
Square Triangle
\ /
Pyramid
Pyramid
class 的 MRO:
(__main__.Pyramid,
__main__.Square,
__main__.Rectangle,
__main__.Triangle,
object)
我了解代码背后的总体思路,以及如何使用 super().__init__
将可变关键字参数字典传递给使用 **kwargs
的 superclass。我遇到问题的详细信息是:
- 为什么我们在
Pyramid
class 中使用base=base
而 superclass (Square
) 需要length
争论? - 当我只输入
super().__init__(base, **kwargs)
而不是base=base
时,为什么会报错 init() got参数 'length', 的多个值是因为上面指定的kwargs["length"]
吗?如果是这样,base=base 是如何解决的? - 为什么我们在 Rectangle 中没有 superclass 而有
super().__init__(**kwargs)
?我的猜测可能是将 kwargs 传递给内置的object
基 class 所以Triangle
可以继承它?但我不确定。 - 为什么
Triangle
也会调用基地 class?这似乎是多余的(即使从 Triangle 中删除super().__init__(**kwargs)
也不会改变任何东西)。
好问题!
因为
Square.__init__
接受**kwargs
我们实际上可以传递我们想要的任何东西而不会得到unexpected keyword argument
错误1.这稍后会变得很方便。它(and/or 它的超类的__init__
方法)不使用的任何关键字参数都将在 MRO 中向上传播,直到我们到达object
.
1通常。在这种情况下,(不必要的)调用super().__init__(**kwargs)
inTriangle.__init__
打破了这种行为。
由于
的多个值的错误kwargs
的扩展,在Pyramid.__init__
中调用super().__init__(base, **kwargs)
时,Square.__init__
实际上是用(2, height=3, length=2)
调用的。由于Square.__init__
的参数称为length
,您会收到有关length
.没错。此外,因为还没有任何东西“消耗”
base
关键字参数,所以Triangle.__init__
将接收它。也对。绝对没有必要在
Triangle.__init__
中调用super().__init__(**kwargs)
,尤其是到那时kwargs
是一个空字典(它包含的所有关键字参数都已经被消耗)。