2017-08-24 69 views
3

我在Python的输入系统和__slots__之间发生冲突。这是一个小的可重现的例子。__slots__与泛型类中的类变量冲突

from typing import TypeVar, Generic, Sequence 

T = TypeVar("T") 

class TestGeneric(Sequence, Generic[T]): 
    __slots__ = ("test",) 

    def __init__(self, test: T): 
     self.test = [test] 

    def __iter__(self): 
     return iter(self.test) 
    def __len__(self): 
     return len(self.test) 

    def __contains__(self, item): 
     return item in self.test 

    def __getitem__(self, _): 
     return self.test[0] 

现在每当我尝试指定内容类型时,例如

V = TestGeneric[int] 

我得到

ValueError: 'test' in __slots__ conflicts with class variable 

我在课堂上使用Generics无缝隙很多,所以我觉得这个错误已被链接到__slots__。此外,如果您删除__slots__

回答

1

我会说这是typing模块中的一个错误,它在创建新类型时没有正确考虑__slots__

这个问题可以用这个很短的例子被复制:

>>> class MyClass: 
... __slots__ = ('my_member',) 
... 
>>> type('MySubClass', (MyClass,), dict(MyClass.__dict__)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: 'my_member' in __slots__ conflicts with class variable 

类型调用type()以上是发生了什么typing模块在幕后的等价物。

此异常的事实,当你使用__slots__,您指定的成员会被自动添加到dict类型造成的:通过MyClass.__slots__一次:

>>> MyClass.__slots__ 
['my_member'] 
>>> MyClass.__dict__ 
mappingproxy({..., 'my_member': <member 'my_member' of 'MyClass' objects>, ...}) 

当我们这样做type('MySubClass', (MyClass,), dict(MyClass.__dict__)),我们传递my_member两次,一旦通过MyClass.__dict__,类型机械正在抱怨它。

除了避免使用__slots__或致电register()而不是继承子类之外,您可以做的并不多。

+0

我认为这是一个错误,但想确定。我已经提交了一份报告。 –