我有一个比较大的Python项目,为了尽量减少调试时间,我尝试模拟较低级别语言的一些方面。具体来说
我一直在使用mypy捕捉类型转换错误,并在类实例中定义__slots__
,以防止动态添加。在
在某一点上,我需要一个列表,其中包含两个不同的子类(它们有相同的父类),它们具有稍微不同的属性。mypy不喜欢这样一个事实:对一个列表项的属性的调用并没有出现在所有的列表项中。但是,使父对象过于一般化意味着在另一个子对象中动态添加变量并没有被阻止。在
为了解决这个问题,我调试/brute强迫自己使用下面的代码示例:
from abc import ABCMeta
from typing import List
class parentclass(metaclass=ABCMeta):
__slots__:List[str] = []
name: None
class withb(parentclass):
__slots__ = ['b','name']
def __init__(self):
self.b: int = 0
self.name: str = "john"
class withf(parentclass):
__slots__ = ['f','name']
def __init__(self):
self.name: str = 'harry'
self.f: int = 123
bar = withb()
foo = withf()
ls: List[parentclass] = [bar, foo]
ls[0].f = 12 ## Needs to fail either in Python or mypy
for i in range(1):
print(ls[i].name)
print(ls[i].b) ## This should NOT fail in mypy
这很管用。但我不知道为什么。如果我不初始化父级中的变量(即只将它们设置为None
或{f:int = 0
,那么它们就把它放入子元素中,我的检查就不能再工作了。在
有人能向像我这样的白痴解释这种行为吗?我很想知道,这样我就不会把事情的执行搞得一团糟,也不会引入更多的错误!在
顺便说一句:我确实试过列出[Union[withb,withf]],但那也没用!在
将名称设置为父级中的值将创建类属性。即使实例受到
__slots__
的限制,类本身也可以有非时隙名称,并且当实例缺少属性时,总是检查其类是否具有类级别的属性(这就是您可以在实例上调用方法的方式)。在尝试通过实例分配给类属性并不能替换类属性。
instance.attr = someval
将始终尝试在实例上创建不存在的属性(隐藏class属性)。当层次结构中的所有类都使用__slots__
(不带__dict__
槽)时,这将失败(因为槽不存在)。在当您仅仅针对}属性。如果所有子类都必须有一个
f: None
时,您已经注释了名称f
,但实际上并没有创建类属性;实际上创建它的是默认值的赋值。当然,在您的例子中,在父类中分配默认值是没有意义的,因为并不是所有子类都有f
或{name
,那么它应该是父类的一部分,例如:如果目标是根据子类的类型动态选择是使用},那么您可以将使用它的代码更改为:
^{pr2}$f
还是{在不需要}),您可以explicitly ^{} the type ,但要知道这会放弃},作为一个异构容器)被误用。在
isinstance
的情况下(您知道类型,因为某些索引保证是withf
或{mypy
的检查能力;列表是一个同质的数据结构,并且使位置变得重要(la{相关问题 更多 >
编程相关推荐