主要 class 输入 Python mixins
Main class typing in Python mixins
我有一个 class 拆分成混合:
class MyObject(MyObjectFilesMixin, MyObjectProcessingMixin, ...):
def __init__(self, value):
self.value = self.preprocess(value)
mixin 看起来像这样:
class MyObjectFilesMixin:
def load_from_file(cls, filename):
return ...
现在我想在 class 和 mixins 中添加类型:
class MyObjectFilesMixin:
def load_from_file(cls, filename: str) -> MyObject:
return ...
class MyObjectProcessingMixin:
def preprocess(self: MyObject, value: bytes):
return value # logic is omitted
def append(self: MyObject, other: MyObject):
self.value += other.value
但是会导致循环链接。当然我可以创建一些MyObjectBase
(遵循依赖倒置原则),这样MyObject
也会继承这个class,mixins会把它当作argument/return类型使用,但是这个无论如何都会导致错误的类型。可以修复吗??
我错过了很多来自 C++ 的头文件+源文件
在使用 mixin 继承的情况下,protocols and structural subtyping and TYPE_CHECKING 可以通过避免循环导入来帮助成功键入 类,它可能看起来像这样:
# my_object.py
from mixins import ProcessingMixin
class MyObject(ProcessingMixin):
def __init__(self, value):
self.value = self.preprocess(value)
def some_process(self, value) -> bytes:
...
# mixins.py
from typing import Protocol, TYPE_CHECKING
if TYPE_CHECKING:
from my_object import MyObject
class ValueObjectProto(Protocol):
"""Protocol for value processing methods."""
value: bytes
def preprocess(self, value: bytes) -> bytes: ...
def some_process(self, value) -> bytes: ...
class MyObjectFilesMixin:
def load_from_file(cls, filename: str) -> MyObject:
return cast(Type[MyObject], cls)(1)
class ProcessingMixin:
def preprocess(self: ValueObjectProto, value: bytes) -> bytes:
value = self.some_process(value)
return value
def append(self: ValueObjectProto, other: ValueObjectProto) -> None:
self.value += other.value
我发现了如何在没有协议或其他不必要的代码的情况下完成这个技巧,DRY!我的解决方案很简单:
from typing import TYPE_CHECKING, Type
if TYPE_CHECKING:
from my_object import MyObject
MO = Type('MyObject')
class MyObjectFilesMixin:
def load_from_file(cls: MO, filename: str) -> 'MyObject':
# Now I'm able to access all the methods of MyObject by cls
# with correct IDE support and MyPy checking
return ...
class MyObjectProcessingMixin:
def preprocess(self: 'MyObject', value: bytes):
return value # logic is omitted
def append(self: 'MyObject', other: 'MyObject'):
self.value += other.value
但是,我收到另一个警告,可能是因为 MyPy 不希望将子项用作父项中的类型:
Mypy: The erased type of self "Type[... MyObject]" is not a supertype of its class "Type[...MyObjectFilesMixin]"
但是要让 IDE 和 MyPy 正确查看和理解这些方法和类型需要付出一点代价!
我有一个 class 拆分成混合:
class MyObject(MyObjectFilesMixin, MyObjectProcessingMixin, ...):
def __init__(self, value):
self.value = self.preprocess(value)
mixin 看起来像这样:
class MyObjectFilesMixin:
def load_from_file(cls, filename):
return ...
现在我想在 class 和 mixins 中添加类型:
class MyObjectFilesMixin:
def load_from_file(cls, filename: str) -> MyObject:
return ...
class MyObjectProcessingMixin:
def preprocess(self: MyObject, value: bytes):
return value # logic is omitted
def append(self: MyObject, other: MyObject):
self.value += other.value
但是会导致循环链接。当然我可以创建一些MyObjectBase
(遵循依赖倒置原则),这样MyObject
也会继承这个class,mixins会把它当作argument/return类型使用,但是这个无论如何都会导致错误的类型。可以修复吗??
我错过了很多来自 C++ 的头文件+源文件
在使用 mixin 继承的情况下,protocols and structural subtyping and TYPE_CHECKING 可以通过避免循环导入来帮助成功键入 类,它可能看起来像这样:
# my_object.py
from mixins import ProcessingMixin
class MyObject(ProcessingMixin):
def __init__(self, value):
self.value = self.preprocess(value)
def some_process(self, value) -> bytes:
...
# mixins.py
from typing import Protocol, TYPE_CHECKING
if TYPE_CHECKING:
from my_object import MyObject
class ValueObjectProto(Protocol):
"""Protocol for value processing methods."""
value: bytes
def preprocess(self, value: bytes) -> bytes: ...
def some_process(self, value) -> bytes: ...
class MyObjectFilesMixin:
def load_from_file(cls, filename: str) -> MyObject:
return cast(Type[MyObject], cls)(1)
class ProcessingMixin:
def preprocess(self: ValueObjectProto, value: bytes) -> bytes:
value = self.some_process(value)
return value
def append(self: ValueObjectProto, other: ValueObjectProto) -> None:
self.value += other.value
我发现了如何在没有协议或其他不必要的代码的情况下完成这个技巧,DRY!我的解决方案很简单:
from typing import TYPE_CHECKING, Type
if TYPE_CHECKING:
from my_object import MyObject
MO = Type('MyObject')
class MyObjectFilesMixin:
def load_from_file(cls: MO, filename: str) -> 'MyObject':
# Now I'm able to access all the methods of MyObject by cls
# with correct IDE support and MyPy checking
return ...
class MyObjectProcessingMixin:
def preprocess(self: 'MyObject', value: bytes):
return value # logic is omitted
def append(self: 'MyObject', other: 'MyObject'):
self.value += other.value
但是,我收到另一个警告,可能是因为 MyPy 不希望将子项用作父项中的类型:
Mypy: The erased type of self "Type[... MyObject]" is not a supertype of its class "Type[...MyObjectFilesMixin]"
但是要让 IDE 和 MyPy 正确查看和理解这些方法和类型需要付出一点代价!