python类型提示数据级属性的注释

发布于 2025-02-01 09:53:59 字数 331 浏览 4 评论 0原文

我有一个dataclass,我将其用作常数存储。

@dataclass
class MyClass:
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"

我有一个函数:

def my_func(value: ?):
   print(value)

我想向我的功能添加注释,以指定可能的 value myclass

如何做的属性之一(我使用的是Python 3.10)?

I have a dataclass and I use it as a constant store.

@dataclass
class MyClass:
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"

I have a function:

def my_func(value: ?):
   print(value)

I want to add annotation to my function to specify that possible value is one of attribute of MyClass

How to do it (I am using python 3.10) ?

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

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

发布评论

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

评论(2

微暖i 2025-02-08 09:53:59

希望我不要误解问问,请告诉我是否这样。但是我认为在这种情况下,最好使用 enum a>类型为Python。

这是一个简单的示例:

from enum import Enum


class MyEnum(Enum):
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"

然后回答第二部分,为注释变成myenum。这意味着这种类型的任何枚举成员,而不是类型(类)本身。

def my_func(value: MyEnum):
    print(value, value.name, value.value)

将所有这些放在一起,就像:

from enum import Enum


class MyEnum(Enum):
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"


def my_func(value: MyEnum):
    # technically you can remove this check
    if not isinstance(value, MyEnum):
        return

    print(value, value.name, value.value)

# note below: only type checker or ide complain, but code still runs fine

my_func('hello')            # not OK!
my_func('second')           # not OK!
my_func(MyEnum)             # not OK!
my_func(MyEnum.CONSTANT_1)  # OK

Hopefully I not misunderstand the ask, please let me know if so. But I think in this case is best to use Enum type in python.

Here is a simple example:

from enum import Enum


class MyEnum(Enum):
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"

Then to answer the second part, for annotation the ? becomes a MyEnum. This means any enum member of this type, but not the type (class) itself.

def my_func(value: MyEnum):
    print(value, value.name, value.value)

Putting it all together, it becomes like:

from enum import Enum


class MyEnum(Enum):
    CONSTANT_1 = "first"
    CONSTANT_2 = "second"


def my_func(value: MyEnum):
    # technically you can remove this check
    if not isinstance(value, MyEnum):
        return

    print(value, value.name, value.value)

# note below: only type checker or ide complain, but code still runs fine

my_func('hello')            # not OK!
my_func('second')           # not OK!
my_func(MyEnum)             # not OK!
my_func(MyEnum.CONSTANT_1)  # OK
〆凄凉。 2025-02-08 09:53:59

我想您在问一个 xy问题。从您的评论中的响应来看,您似乎想要的是:

  • 具有类似类的界面来保持一堆恒定的值。
  • 将论点限制为仅采用上述值。

如rv.kvetch的答案,常规的做法是使用枚举。我不确定您的意思是“想跳过.value”,value枚举字段只是为您提供了与该枚举相关的内容,我会说这一点都不重要。以下是一个示例:

class StrEnum(enum.Enum):
  FIRST = "first"
  SECOND = "second"

class StrEnum2(enum.Enum):
  FIRST = "first"
  SECOND = "second"

print(StrEnum.FIRST.value)  # first
print(StrEnum2.FIRST.value)  # first
print(StrEnum.FIRST.value == StrEnum2.FIRST.value)  # True
print(StrEnum.FIRST == StrEnum2.FIRST)  # False

class IntEnum(enum.Enum):
  FIRST = enum.auto()
  SECOND = enum.auto()

print(IntEnum.FIRST.value)  # 1
print(IntEnum.SECOND.value)  # 2

我想与此示例显示的是两件事:

  1. 如果您只是在比较枚举,您真的不需要value
  2. 您甚至不需要手动为枚举分配值;您可以使用enum.auto()自动分配其唯一值。

因为归根结底,枚举本身已经代表了有效选择之间的选择,因此它具有什么价值都没关系。


也就是说,如果您想要的只是对参数可以键入的值进行类型限制,而不必使用枚举,那么您可以使用文字类型。参见此答案细节。就您的示例而言,您可以做类似的事情:

from typing import Literal, Final

def my_func(value: Literal["first", "second"]):
   print(value)

my_func("first")  # ok
my_func("not first")  # bad
x = "first"
y: Final = "first"
my_func(x)  # bad, because `x` is not final
my_func(y)  # ok

但是请注意,类型的注释并不能真正阻止您调用具有无效值的函数,这只是IDE和类型检查器的提示。

I think you're asking an XY problem. From your response in the comments, it seems like what you want is rather:

  • Have a class-like interface to hold a bunch of constant values.
  • Constraint the argument to only take the above values.

As as mentioned in rv.kvetch's answer, the conventional way of doing this is to use enums. I'm not sure what you mean by "wanting to skip .value", the value field of an enum simply gives you what's associated with that enum, and I would say that it's not important at all. Here's an example:

class StrEnum(enum.Enum):
  FIRST = "first"
  SECOND = "second"

class StrEnum2(enum.Enum):
  FIRST = "first"
  SECOND = "second"

print(StrEnum.FIRST.value)  # first
print(StrEnum2.FIRST.value)  # first
print(StrEnum.FIRST.value == StrEnum2.FIRST.value)  # True
print(StrEnum.FIRST == StrEnum2.FIRST)  # False

class IntEnum(enum.Enum):
  FIRST = enum.auto()
  SECOND = enum.auto()

print(IntEnum.FIRST.value)  # 1
print(IntEnum.SECOND.value)  # 2

What I want to show with this example are two things:

  1. You don't really need .value at all if you're just comparing enums.
  2. You don't even need to manually assign values to the enums; you can use enum.auto() to auto-assign a unique value to it.

Because at the end of the day, enums themselves already represent a choice among valid choices, so it doesn't matter what values it has.


That said, if what you want is just to put a type constraint on what values an argument can type, and not have to use enums, then you can use the Literal type. See this answer for details. For your example, you could do something like:

from typing import Literal, Final

def my_func(value: Literal["first", "second"]):
   print(value)

my_func("first")  # ok
my_func("not first")  # bad
x = "first"
y: Final = "first"
my_func(x)  # bad, because `x` is not final
my_func(y)  # ok

But note that type annotations don't really prevent you from calling a function with an invalid value, it's just a hint for IDEs and type checkers.

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