Python:用于通过继承装饰自定义数据类的类型提示

问题描述 投票:0回答:1

情况是这样的。我正在尝试减少项目中样板代码的数量。这是设置的简化版本。

from __future__ import annotations

import dataclasses
import typing as t
import types

_Self = t.TypeVar("_Self", bound="A")

class A:
  """Base class for all classes"""
  @classmethod
  def create(cls: type[_Self], *args, **kwargs) -> _Self:
    return cls(*args, **kwargs)

  def do_something(self) -> None:
    """a 'void' method"""
    pass


class B(A):
  """A secondary base class for the future dataclasses; NOTE: inheritance from A!"""


T = t.TypeVar("T", bound=B)
TCallable = t.Callable[[type], type[T]]


def decorator(**kwargs) -> TCallable:
  """A decorator for reducing boilerplate"""
  def _decorator(cls: type) -> type[B]:
    return types.new_class(
      cls.__name__, 
      (
        dataclasses.dataclass(**{"frozen": True, "kw_only": True, **kwargs}(cls), 
        B,
      ),
    )
  return _decorator


@decorator(repr=False)
class Test:
   """This is an implementation of the dataclass, subclassed from B, subclassed from A"""
   name: str
   
    def __repr__(self) -> str:
      return self.name
    
    def do_something_else(self) -> None:
      self.do_something() # <- not recognized by pyright

问题是我的静态类型检查器无法识别

class A
实例中解析顺序顶部的
class Test
中的方法。

我在 VSCode 中使用 Pylance/Pyright。

编辑以纠正装饰器中的错误

python python-typing pyright
1个回答
0
投票

首先,我应该注意它可以在没有装饰器的情况下实现,如下所示:

@dataclasses.dataclass(frozen = True, kw_only = True, repr=False)
class Test(B):
   """This is an implementation of the dataclass, subclassed from B, subclassed from A"""
   name: str
   
   def __repr__(self) -> str:
      return self.name
    
   def do_something_else(self) -> None:
      self.do_something()

但是我们假设,出于某种原因它需要存在。此示例假设您只是想避免多次输入

frozen
kw_only

from __future__ import annotations

import dataclasses
import typing as t

_Self = t.TypeVar("_Self", bound="A")

class A:
  """Base class for all classes"""
  @classmethod
  def create(cls: type[_Self], *args, **kwargs) -> _Self:
    return cls(*args, **kwargs)

  def do_something(self) -> None:
    """a 'void' method"""
    pass

class B(A):
  """A secondary base class for the future dataclasses; NOTE: inheritance from A!"""

@t.dataclass_transform()
def decorator(**kwargs):
  def _decorator(cls: type) -> type[B]:
    return dataclasses.dataclass(**{"frozen": True, "kw_only": True, **kwargs})(cls)
  return _decorator


@decorator(repr=False)
class Test(B):
   """This is an implementation of the dataclass, subclassed from B, subclassed from A"""
   name: str
   
   def __repr__(self) -> str:
      return self.name
    
   def do_something_else(self) -> None:
      self.do_something()

继承方面目前不可能添加到类型中,这就是为什么我让它从 B 继承。总的来说,这可能是更好的实践,因为它使继承结构更清晰。不过,最终可能可以使用

Intersection
进行打字。希望这有用!

© www.soinside.com 2019 - 2024. All rights reserved.