如何完善python类型的提示,以提示在继承类时返回类实例的方法?

发布于 2025-02-13 21:59:21 字数 1490 浏览 0 评论 0原文

我有一个父母,其方法可以返回该类的实例。 该课程有一个(或几个)儿童课。

如何提供类型提示以表明任何子类中的方法调用将返回该孩子类的实例,而不是父母类的实例?

例如,使用以下代码:

from random import randint

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> "Person":
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass

def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)

linter mypy会引起错误:

error: Argument 1 to "welcome_player" has incompatible type "Person"; expected "Player"
Found 1 error in 1 file (checked 1 source file)

当然,您可以执行以下操作,但是如果父母类多次继承,那就很重:

from random import randint
from typing import cast


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> "Person":
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    @classmethod
    def get_random_person(cls) -> "Player":
        return cast(Player, super().get_random_person())


def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)

任何建议:以明智的方式实现这一目标?

I have a parent class with a method that returns an instance of that class.
This class has one (or several) children classes.

How to provide type hints to indicate that the method call on any child class will return an instance of that very child class and not the parent class?

For example, with the following code:

from random import randint

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> "Person":
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass

def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)

The linter mypy would raise an error:

error: Argument 1 to "welcome_player" has incompatible type "Person"; expected "Player"
Found 1 error in 1 file (checked 1 source file)

Of course, you could do something like the following, but that is very heavy if the parent class is inherited multiple times:

from random import randint
from typing import cast


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> "Person":
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    @classmethod
    def get_random_person(cls) -> "Player":
        return cast(Player, super().get_random_person())


def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)

Any suggestion on a smart way to achieve that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

行雁书 2025-02-20 21:59:22

您可以使用 typing.typing.typevar typing 使用参数BOND 模拟:

from random import randint
from typing import TypeVar, Type


Self = TypeVar('Self', bound='Person')


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls: Type[Self]) -> Self:
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass


def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player: Player = Player.get_random_person()
welcome_player(player)

Python 3.11将添加 self code> self code> 但尚未正式发布。 键入 - 延迟在较旧版本中可以访问,尽管mypy会抱怨错误:变量“ typing_extensions.self”无效作为类型)。

from random import randint
from typing_extensions import Self


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> Self:
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass

def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)

You can use typing.TypeVar with parameter bound to simulate:

from random import randint
from typing import TypeVar, Type


Self = TypeVar('Self', bound='Person')


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls: Type[Self]) -> Self:
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass


def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player: Player = Player.get_random_person()
welcome_player(player)

Python 3.11 will add the Self type, but it has not been officially released yet. This is accessible in older versions with the typing-extensions, although mypy will complain that error: Variable "typing_extensions.Self" is not valid as a type).

from random import randint
from typing_extensions import Self


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def get_random_person(cls) -> Self:
        return cls("Random Guy", randint(18, 65))


class Player(Person):
    pass

def welcome_player(player: Player):
    print(f"Welcome {player.name}")


player = Player.get_random_person()
welcome_player(player)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文