![](/img/trans.png)
[英]How to modify the attribute of super class using subclass in python?
[英]Python - call super() as attribute of subclass
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Triangle(Point):
def __init__(self, v1, v2, v3):
"""Create a new Triangle with vertices (v1, v2, v3)."""
self.v1 = super().__init__(x=v1[0], y=v1[1])
self.v2 = super().__init__(x=v2[0], y=v2[1])
self.v3 = super().__init__(x=v3[0], y=v3[1])
tri = Triangle((1,1),(1,10),(1,5))
我正在嘗試調用 super().__init__() 作為子類的屬性,但是當我執行上面的代碼時,我收到一個錯誤消息:
__init__() missing 1 required positional argument: 'y'
它指向子類中定義 self.v1 的那一行。 這里有什么明顯的錯誤嗎? 我嘗試將 self 和其他測試參數添加到 super().__init__() 調用中只是為了測試一下,但我總是得到同樣的錯誤。
您的代碼存在一些問題。
super().__init__
沒有做你認為的那樣。 在每次調用__init__
您實際上是在tri
的范圍內運行Point.__init__
。 如果你print(tri)
你會看到tri
有x
和y
屬性。
tri = Triangle((1,1),(1,10),(1,5))
print(tri.x) # 1
print(tri.y) # 5
您真正想要做的是為每個頂點創建一個Point
實例。 要做到這一點並使用super
你可以使用self.v1 = super().__new__(x=v1[0], y=v1[1])
。 __new__
將構造一個super
類的新對象並將該對象分配給self.v1
。
class Triangle(Point):
def __init__(self, v1, v2, v3):
"""Create a new Triangle with vertices (v1, v2, v3)."""
self.v1 = super().__new__(x=v1[0], y=v1[1])
tri = Triangle((1,1),(1,10),(1,5))
print(tri.v1) # Point (x=1, y=1
print(tri.v2) # Point (x=1, y=10)
現在你有了一個工作示例,但你仍然可以做得更好。 看到您在Triangle
中使用的Point
的唯一部分是__new__
為什么我們還要從類繼承? 在這種情況下,我將刪除繼承並只創建新實例而不調用super()
。
此外,在 python 3 中,您不需要從object
繼承。
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
class Triangle():
def __init__(self, v1, v2, v3):
"""Create a new Triangle with vertices (v1, v2, v3)."""
self.v1 = Point(x=v1[0], y=v1[1])
self.v2 = Point(x=v2[0], y=v2[1])
self.v3 = Point(x=v3[0], y=v3[1])
tri = Triangle((1,1),(1,10),(1,5))
print(tri.v1) # Point (x=1, y=1
print(tri.v2) # Point (x=1, y=10)
作為額外的 - 我會推薦@Oliver 的實現。 它更干凈,不會創建那么多對象。 唯一的副作用是將v1
重命名為x
等。
你的問題不是真正的super
,而是整個繼承。
一類A
應該從一個類繼承B
如果的目的A
實際上是定義為的目的B
與額外的屬性。 繼承擴展了定義。
在Triangle
和Point
的情況下,您實際想要的代碼(已在 Alexander Kamyanskiy 和 Jim Wright 的答案中給出)不需要繼承。 此外,從數學上講,三角形不是具有額外屬性的點。
這是一個有意義的繼承示例。
class Point:
def __init__(self, x, y)
self.x = x
self.y = y
# A point in 3D really is a point in 2D with an extra coordinate
class Point3D(Point)
def __init__(self, x, y, z):
self.z = z
super().__init__(x, y)
下面是一個繼承的例子,雖然在編程上是正確的,但實際上並沒有什么意義。
class Plant:
def __init__(self, type):
self.type= type
# Let me check my biology textbooks...
class Animal(Plant):
def __init__(self, kind, favorite_food):
self.kind = kind
# Herbivores only please
self.favorite_food = Plant(favorite_food)
使用另一個類作為屬性不會強制您繼承它。 在上面的例子中,你告訴 Python 任何Animal
也是Plant
一個實例,根據我的小生物學背景是不正確的。
當你被召喚時
self.v1 = super().__init__(x=v1[0], y=v1[1])
它調用 Point 類的__init__()
方法,但不返回 Point 的實例,它返回 None (並將 x,y 屬性添加到 Triangle 類的tri
實例中)。
用 3 Points 實例化 Triangle 代碼可能如下所示:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Triangle(object):
def __init__(self, v1, v2, v3):
"""Create a new Triangle with vertices (v1, v2, v3)."""
self.v1 = Point(x=v1[0], y=v1[1])
self.v2 = Point(x=v2[0], y=v2[1])
self.v3 = Point(x=v3[0], y=v3[1])
tri = Triangle((1,1),(1,10),(1,5))
17 self.v1 = Point(x=v1[0], y=v1[1])
---> 18 self.v2 = Point(x=v2[0], y=v2[1])
19 self.v3 = Point(x=v3[0], y=v3[1])
ipdb> self.v1
<__main__.Point object at 0x7f18c48da048>
ipdb> self.v1.x
1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.