Python - TypedDict类型提示键

bq9c1y66  于 2023-03-20  发布在  Python
关注(0)|答案(1)|浏览(172)

我有2个类。一个继承了TypedDict类,在这个类中我有一组键,它们应该接受某种类型的数据:

class UserType(TypeDict):
   first_name: str
   last_name: str
   age: int

在另一个类Customer中,我使用UserType dict来存储客户的信息,并且有一个更新信息的方法:

class Customer:
   def __init__():
     self._userInfo: UserType = {
       "first_name": "John",
       "last_name": "John",
       "age": 27
    }
    
    def set_info(key: str, val: Any):
      self._userInfo[key] = val

set_info中,我想键入hint key,以仅显示在UserType中定义的键,例如:

customer = Customer()
customer.set_info(SHOULD HINT KEY HERE (first_name, ...), "Somedata")

dict.我试过这样的话:

def set_info(key: UserType, val: Any):
   ...

但这并不奏效。我想,我正试图将它用作接口,因为我来自严格的类型化语言背景。有什么想法可以实现这一点吗?我可以灵活地改变它的其他东西,而不是dict

mbyulnm0

mbyulnm01#

TypedDict不将其键公开为不同类型,也没有真正好的方法来定义这样的类型。

不推荐

有些人使用typing.Literal,但这是为了,嗯,* 文字 *。使用key: Literal["first_name", "last_name", "age"]允许c.set_info("first_name", "bob"),但不允许k = "first_name"; c.set_info(k, "bob"),因为k不是文字。我不建议这样做,但我觉得需要解决这个问题。
"更好"
另一种方法是显式定义单独的枚举类型,并使用其成员(而不是原始键)作为参数。

class CustomerKey(enum.StrEnum):
    FIRST_NAME = "first_name"
    LAST_NAME = "last_name"
    AGE = "age"

# This could (somewhat awkwardly) also be defined as
#
#   CustomerKey = enum.StrEnum(dict(zip(map(str.upper, UserType.__annotation__),
#                                       UserType.__annotation__)))
#
# to avoid repetition of the exact keys.

class Customer:
    ...

    def set_info(key: CustomerKey, val: Any):     
        self._userInfo[key] = val

更好

这是假设您没有很好的理由单独存储属性,并且只使用TypedDict作为类方法的参数,例如,

@dataclasses.dataclass
class Customer:
    first_name: str
    last_name: str
    age: int

    @classmethod
    def from_dict(cls, d: UserType):
        return cls(**d)

最佳(假设)

下面的内容不要读得太多,我主要是在考虑TypeDict如何将其包含的信息公开为类型提示。
在理想的情况下,TypedDict的键本身会形成一个类型。

class Customer:
    ...

    def set_info(key: UserType.keys, val: Any):
        ...

更好的是,还有一种方法可以将分配给key的值绑定到一个可以用来注解val的类型,这样,如果key == "first_name",则val必须具有type 'str。(其中类型可以依赖于值)、单例类型(其中每个值都有一个关联的类型,该类型 * 仅 * 包含该值)和泛型。

def set_info(key: UserType.keys, val: UserType[key])

相关问题