Python 3.6:我想念一些泛型打字超链接继承

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)
  • 似乎使用泛型类创建使超级无法找到父类初始化器,非?

  • 我错过了什么 ?

use*_*ica 5

这不是泛型打字的意思.当你申报时

class Hero(typing.Generic[RaceT, ClassT]):
    ...
Run Code Online (Sandbox Code Playgroud)

那意味着Hero需要两个类型参数.它并不意味着它Hero[Human, Fighter]Human或者的子类,而Fighter不仅仅是List[int]它的子类int.通用类型不是动态调整类的超类的方法.