EZL*_*ner 1 python dictionary python-3.6
编辑2:最后我能够生成一个MWE:
from typing import Generic, TypeVar
T = TypeVar('T')
class Cache:
__dict = {}
@classmethod
def add(cls, item):
cls.__dict[item] = (item, [item, item, item, {item: item}])
print('On setting:', item in cls.__dict)
def __init_subclass__(cls, **kwargs):
Cache.add(cls)
class Class(Cache, Generic[T]):
pass
d = Cache._Cache__dict
tp = list(d)[0]
print('On checking:', tp in d)
Run Code Online (Sandbox Code Playgroud)
在 python 3.6 中,输出是:
On setting: True
On checking: False
Run Code Online (Sandbox Code Playgroud)
而在 3.8 中则是:
On setting: True
On checking: True
Run Code Online (Sandbox Code Playgroud)
如果这还不够好奇,如果我删除 的继承Generic[T],一切都很好。
原来的
我正在使用 Python 3.6,KeyError当尝试从字典中获取密钥时,我得到了:
On setting: True
On checking: False
Run Code Online (Sandbox Code Playgroud)
这意味着从字典中获取的键会导致此异常。请注意,d只有一个条目。键类型是一个类型对象GenericMeta,其元类是这样的,所以这可能是问题所在吗?
我使用调试器验证了以下属性:
id(tp)多次调用都是一样的。hash(tp)多次调用都是一样的。tp is list(d.keys())[0]tp == list(d.keys())[0]len(d) == 1编辑:
print(type(tp)) # <class 'typing.GenericMeta'>print(type(tp)) # <class 'dict'>我的问题是:这种行为的原因可能是什么?
由于某些软件包的兼容性问题,我无法更新 python 版本,所以请不要告诉我更新,除非这是一个已知的错误,并在以后的版本中解决了。
这是一个初始化顺序问题。
在 Python 3.6 上,Class是typing.GenericMeta. typing.GenericMeta在 中执行重要的初始化__new__,但初始化只能在type.__new__返回要初始化的内容后开始。type.__new__负责调用__init_subclass__,因此您可以在发生__init_subclass__任何GenericMeta初始化之前运行。
当您__init_subclass__添加Class到字典时,尚未执行正确工作==所需的初始化。hash此操作最终使用无效的哈希值。稍后,初始化完成后,查找将使用正确的哈希值,但找不到Class.
在后来的 Python 版本中,整个泛型类的实现被彻底改变。typing.GenericMeta不复存在。
| 归档时间: |
|
| 查看次数: |
368 次 |
| 最近记录: |