我正在尝试创建一个继承泛型类Sprite
的类T
,其范围是作为类Object
的子类。类Text
是类Object
的子类。这是类Text
,由外部库提供:
# text.py
class Text(Object):
# ignored properties...
def __init__(self, text="placeholder text", **kwargs):
super().__init__(object_type=Text.object_type, text=text, **kwargs)
这是我自己写的课Sprite
。
# sprite.py
from typing import TypeVar, Generic
T = TypeVar('T', bound=Object)
class Sprite(Generic[T]):
def __init__(self, **kwargs):
super(Sprite, self).__init__(self, clickable=True, evt_handler=self.click_wrapper, **kwargs)
这样的Sprite
实例由以下方法初始化:
sprite = Sprite[Text](
text="This is a sprite!",
object_id="spriteTest",
# other similar arguments...
)
这就是抛出的错误:
Exception thrown in main()! Terminating main...
Traceback (most recent call last):
File "sprite.py", line 79, in main
sprite = Sprite[Text](
File "C:\ProgramData\Anaconda3\lib\typing.py", line 687, in __call__
result = self.__origin__(*args, **kwargs)
File "sprite.py", line 47, in __init__
super(Sprite, self).__init__(self, clickable=True, evt_handler=self.click_wrapper, **kwargs)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
为什么这不管用?
发布于 2022-06-20 18:10:58
我相信您误解了泛型类型变量。首先,让我尝试将您的bug降到它的最小变体:
class Sprite:
def __init__(self, **kwargs):
super().__init__(**kwargs)
Sprite(text="My text")
这个非常简单的程序抛出与您完全相同的异常:
Traceback (most recent call last):
File ".../72690805.py", line 57, in <module>
Sprite(text="My text")
File ".../72690805.py", line 55, in __init__
super().__init__(**kwargs)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
这里的关键是,它是object
,您不能为它指定除一个参数之外的任何其他内容。换句话说,Sprite
的超类在我们两种情况下都是object
(即默认的Object
对象,而不是Object
类)。您的Sprite
类根本没有一个非默认的超类。
您似乎了解到,无论何时使用super(...).__init__(...)
,您的Text
调用都会初始化Sprite[Text](...)
,但事实并非如此。让我举一个使用中的泛型类型变量的常见示例:
from typing import List, TypeVar, Generic
T = TypeVar('T')
class Queue(Generic[T]):
def __init__(self) -> None:
super().__init__()
self.queue: List[T] = []
def put(self, task: T) -> None:
self.queue.append(task)
def get(self) -> T:
return self.queue.pop(-1)
queue = Queue()
queue.put(12)
queue.put(24)
queue.put(36)
# queue.put('a') # <- A type checker should disallow this
print(queue.get())
print(queue.get())
print(queue.get())
这里,我们有一个简单的队列类,带有put
和get
方法。这些函数通过T得到类型提示的补充,现在类型检查器知道,例如Queue[int]().get
返回一个int
。然而,super().__init__()
仍然只是Python object
的标准初始化。我们不会突然初始化一个int
,这相当于您正在尝试的内容。
总之,每当您发现自己正在使用typing
模块中的功能来尝试一些工作,那么您就犯了一个错误。据我所知,typing
的所有功能都只是“表面的”,被Python忽略了。它允许开发人员使用类型检查器来确保他们不会出错,例如,在用queue.put('a')
初始化queue
时调用Queue[int]()
。重申一下,这个字符的put
仍然将在Python中执行,并且它会将该字符放在队列中,即使Type会告诉您它是错误的。
https://stackoverflow.com/questions/72690805
复制相似问题