首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >继承泛型类型的Python : TypeError: object.__init__()只使用一个参数

继承泛型类型的Python : TypeError: object.__init__()只使用一个参数
EN

Stack Overflow用户
提问于 2022-06-20 17:22:02
回答 1查看 111关注 0票数 0

我正在尝试创建一个继承泛型类Sprite的类T,其范围是作为类Object的子类。类Text是类Object的子类。这是类Text,由外部库提供:

代码语言:javascript
运行
复制
# 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

代码语言:javascript
运行
复制
# 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实例由以下方法初始化:

代码语言:javascript
运行
复制
  sprite = Sprite[Text](
    text="This is a sprite!",
    object_id="spriteTest",
    # other similar arguments...
  ) 

这就是抛出的错误:

代码语言:javascript
运行
复制
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)

为什么这不管用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-20 18:10:58

我相信您误解了泛型类型变量。首先,让我尝试将您的bug降到它的最小变体:

代码语言:javascript
运行
复制
class Sprite:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

Sprite(text="My text")

这个非常简单的程序抛出与您完全相同的异常:

代码语言:javascript
运行
复制
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](...),但事实并非如此。让我举一个使用中的泛型类型变量的常见示例:

代码语言:javascript
运行
复制
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())

这里,我们有一个简单的队列类,带有putget方法。这些函数通过T得到类型提示的补充,现在类型检查器知道,例如Queue[int]().get返回一个int。然而,super().__init__()仍然只是Python object的标准初始化。我们不会突然初始化一个int,这相当于您正在尝试的内容。

总之,每当您发现自己正在使用typing模块中的功能来尝试一些工作,那么您就犯了一个错误。据我所知,typing的所有功能都只是“表面的”,被Python忽略了。它允许开发人员使用类型检查器来确保他们不会出错,例如,在用queue.put('a')初始化queue时调用Queue[int]()。重申一下,这个字符的put仍然将在Python中执行,并且它会将该字符放在队列中,即使Type会告诉您它是错误的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72690805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档