Jer*_*mie 3 python generics inheritance typing super
首先,我运行以下代码,这真的很好:
class Monster:
def __init__(self):
self._can_do = []
print("created a monster")
super().__init__()
class Race(Monster):
""" all races must derive from this """
def __init__(self):
super().__init__()
print("created a race x")
class Human(Race):
def __init__(self):
super().__init__()
self._can_do.append("Do nothing special !")
print("created a human")
class Elf(Race):
def __init__(self):
super().__init__()
self._can_do.append("Avoid sleep")
print("created an elf")
class Class:
""" all classes must derive from this """
def __init__(self):
super().__init__()
print("created a class x")
class Fighter(Class):
def __init__(self):
super().__init__()
self._can_do.append("Hit hard")
print("created a fighter")
class Wizard(Class):
def __init__(self):
super().__init__()
self._can_do.append("Cast spells")
print("created a wizard")
class Hero(Human, Fighter):
def __init__(self):
x = super()
print(f"super = {x}")
super().__init__()
def speak(self):
for action in self._can_do:
print(f"I can {action} !")
print("creating hero 1 :")
hero1 = Hero()
print("hero 1 human fighter says :")
hero1.speak()
Run Code Online (Sandbox Code Playgroud)
结果是:
creating hero 1 :
created a monster
created a class x
created a fighter
created a race x
created a human
hero 1 human fighter says :
I can Hit hard !
I can Do nothing special ! !
Run Code Online (Sandbox Code Playgroud)
然后我又去了,稍微改变一下代码,如下所示,因为那是我想要去的:
(使Hero类动态而不是静态地进行heriting)
import typing
class Monster:
def __init__(self):
self._can_do = []
print("created a monster")
super().__init__()
class Race(Monster):
""" all races must derive from this """
def __init__(self):
super().__init__()
print("created a race x")
class Human(Race):
def __init__(self):
super().__init__()
self._can_do.append("Do nothing special !")
print("created a human")
class Elf(Race):
def __init__(self):
super().__init__()
self._can_do.append("Avoid sleep")
print("created an elf")
class Class:
""" all classes must derive from this """
def __init__(self):
super().__init__()
print("created a class x")
class Fighter(Class):
def __init__(self):
super().__init__()
self._can_do.append("Hit hard")
print("created a fighter")
class Wizard(Class):
def __init__(self):
super().__init__()
self._can_do.append("Cast spells")
print("created a wizard")
RaceT = typing.TypeVar('RaceT', bound=Race)
ClassT = typing.TypeVar('ClassT', bound=Class)
class Hero(typing.Generic[RaceT, ClassT]):
def __init__(self):
super().__init__()
def speak(self):
for action in self._can_do:
print(f"I can {action} !")
print("creating hero 1 :")
hero1 = Hero[Human,Fighter]()
print("hero 1 human fighter says :")
hero1.speak()
Run Code Online (Sandbox Code Playgroud)
这一次,都出错了:
creating hero 1 :
hero 1 human fighter says :
Traceback (most recent call last):
File "./test2.py", line 61, in <module>
hero1.speak()
File "./test2.py", line 54, in speak
for action in self._can_do:
AttributeError: 'Hero' object has no attribute '_can_do'
Run Code Online (Sandbox Code Playgroud)
似乎使用泛型类创建使超级无法找到父类初始化器,非?
我错过了什么 ?
这不是泛型打字的意思.当你申报时
class Hero(typing.Generic[RaceT, ClassT]):
...
Run Code Online (Sandbox Code Playgroud)
那意味着Hero
需要两个类型参数.它并不意味着它Hero[Human, Fighter]
是Human
或者的子类,而Fighter
不仅仅是List[int]
它的子类int
.通用类型不是动态调整类的超类的方法.