【发布时间】:2018-10-27 07:33:28
【问题描述】:
this question 上的后续问题:我在 python 3.5 和 python 3.6 上运行了以下代码 - 结果非常不同:
class Container:
KEYS = ('a', 'b', 'c')
def __init__(self, a=None, b=None, c=None):
self.a = a
self.b = b
self.c = c
def keys(self):
return Container.KEYS
def __getitem__(self, key):
if key not in Container.KEYS:
raise KeyError(key)
return getattr(self, key)
def __str__(self):
# python 3.6
# return f'{self.__class__.__name__}(a={self.a}, b={self.b}, c={self.c})'
# python 3.5
return ('{self.__class__.__name__}(a={self.a}, b={self.b}, '
'c={self.c})').format(self=self)
data0 = Container(a=1, b=2, c=3)
print(data0)
data3 = Container(**data0, b=7)
print(data3)
如上一个问题所述,这引发了
TypeError: type object got multiple values for keyword argument 'b'
在 python 3.6 上。但是在 python 3.5 上我得到了异常:
密钥错误:0
此外,如果我不提出KeyError,而只是在__getitem__ 中打印出key 和return:
def __getitem__(self, key):
if key not in Container.KEYS:
# raise KeyError(key)
print(key)
return
return getattr(self, key)
这将打印出int 序列0, 1, 2, 3, 4, ...。 (python 3.5)
所以我的问题是:
版本之间发生了哪些变化,导致其行为如此不同?
这些整数从何而来?
更新:正如λuser 的评论中所述:实现__iter__ 将改变python 3.5 上的行为以匹配python 3.6 的行为:
def __iter__(self):
return iter(Container.KEYS)
【问题讨论】:
-
我认为你的实现缺少方法
__iter__(返回键)和__len__,然后从collections.abc.Mapping继承,你应该设置。我猜 Python 不知道键是什么,因为你没有实现__iter__,所以它在 python 3.5 中尝试了一些数字。 -
@λuser :你是对的!在这种情况下,只需实现
__iter__就足够了。问题仍然存在......
标签: python python-3.x python-3.5 python-3.6 python-internals