【问题标题】:What is the best generic type hint for a dataclass in python?python中数据类的最佳泛型类型提示是什么?
【发布时间】:2022-01-18 05:25:17
【问题描述】:

我已经开始使用数据类,并且我有一些特定的,例如:

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int
    job:str
    
@dataclass
class Animal:
    name: str
    age: int

然后我有一个像接口这样的抽象类

import abc
from typing import List, Dict


class NameFinder:
    @abc.abstractmethod
    def get_name(self, name: str,being ) :
        pass

class PersonName(NameFinder):
    def get_name(self, name:str, person:Person):
        return person.name

class AnimalName(NameFinder):
    def get_name(self, name:str, animal:Animal):
        return animal.name

什么是可以在抽象类中用作 Person 和 Animal 类的占位符的好的泛型类型提示?

【问题讨论】:

  • 据我所知,这个问题确实与数据类无关。似乎是一个红鲱鱼。在任何情况下,您可能都可以使用绑定的 TypeVar T = TypeVar(T, Animal, Person)
  • 也许你想要一个协议类来断言接收到的类同时具有nameage 属性。
  • NameFinder 没有理由成为一个类,但是:get_name 最坏的情况是可以作为静态方法,并且像大多数静态方法一样,可能可以作为常规函数来实现。
  • @juanpa.arrivillaga 我认为这可能与它有关,因为数据类包装器可以提供一个我不知道的基类。这就是我问的原因。
  • 如果您要添加第三个类(如Vegetable),您还必须更新 typevar。使用协议,Vegetable 会自动包含为协议的“子类”,这仅仅是因为具有name 属性。有许多其他语言必须使用继承来实现,而在 Python 中无需继承就可以做到;这是其中之一。

标签: python abstract-class python-dataclasses


【解决方案1】:

您可以定义一个协议类,它只是断言name 属性的存在。

from typing import Protocol


class Named(Protocol):
    name: str


class NameFinder:
    @staticmethod
    def get_name(obj: Named) -> str:
        return obj.name

# or ...
def name_finder(obj: Named) -> str:
    return obj.name

get_namename_finder 都可以接受PersonAnimal 类型的参数,因为这两个类都为其实例定义了name 属性。无需将类显式标记为实现Named 协议。

【讨论】:

  • 是的,我想到了这一点,但我宁愿避免只为那个打字创建另一个课程。不过谢谢。
  • 我认为它更像是创建一个不同的类,替换 NameFinder 而不是被 NameFinder 使用。
  • 啊,我明白了,那个 protocl 类实际上可能是我想要的,我不能直接将它用作我原始抽象类中 being 的类型吗?
  • 是的。任何具有属性name(无论该属性如何设置)的实例(无论它具有什么类型)都被视为实例Named
  • 我会回溯一点:这对于指定 具有 name 属性的类型很有用,但对 enforce 没有任何作用任何特定类型必须具有该属性。为此,基类仍然更好,但我不确定如何最好地将它与数据类集成。 (很可能,这只是数据类不合适的情况。)
猜你喜欢
  • 2021-11-25
  • 1970-01-01
  • 2019-02-14
  • 2015-12-10
  • 2010-09-06
相关资源
最近更新 更多