假设我定义了以下类:
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
通常,可以通过以下方式之一实例化此类:
>>> MyClass(1,2)
<__main__.MyClass object at 0x8acbf8c>
>>> MyClass(1, y=2)
<__main__.MyClass object at 0x8acbeac>
>>> MyClass(x=1, y=2)
<__main__.MyClass object at 0x8acbf8c>
>>> MyClass(y=2, x=1)
<__main__.MyClass object at 0x8acbeac>
哪个好,花花公子。
现在,我们尝试使用无效的关键字参数,看看会发生什么:
>>> MyClass(x=1, j=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'j'
Python正确引发了类型错误并抱怨unexpected keyword argument 'j'
。
现在,我们可以尝试使用两个无效的关键字参数:
>>> MyClass(i=1,j=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
请注意,两个关键字参数无效,但Python只抱怨其中一个,'i'
。
让我们颠倒无效关键字参数的顺序:
>>> MyClass(j=2, i=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
这很有趣。我更改了无效关键字参数的顺序,但Python仍然决定抱怨'i'
而不是'j'
。所以Python显然不会简单地选择第一个无效的关键来抱怨。
让我们再尝试一下:
>>> MyClass(c=2, i=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
>>> MyClass(q=2, i=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
按字母顺序,我在i
之前尝试了一封信,在i
之后尝试了一封信,因此Python并没有按字母顺序投诉。
以下是更多内容,这次i
位于第一位:
>>> MyClass(i=1, j=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
>>> MyClass(i=1, b=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'i'
>>> MyClass(i=1, a=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'a'
啊哈!我得到了抱怨'a'
而不是'i'
。
我的问题是,当为类构造函数提供无效的关键字参数时,Python如何确定要投诉哪一个?
答案 0 :(得分:17)
关键字参数存储在字典中,并且字典顺序(例如,任意,基于散列算法,散列冲突和插入历史记录)适用。
对于您的第一个示例,包含i
和j
键的字典会导致首先列出i
:
>>> dict(j=2, i=1)
{'i': 1, 'j': 2}
请注意,{...}
文字字母表示法从右到左插入键,而关键字解析从左到右插入关键字(这是CPython实现细节);因此在上面的例子中使用dict()
构造函数。
当两个键散列到同一个广告位时,这很重要,例如i
和a
:
>>> dict(i=1, a=2)
{'a': 2, 'i': 1}
>>> {'i': 1, 'a': 2}
{'i': 1, 'a': 2}
字典输出顺序高度依赖于插入和删除历史和特定的Python实现;例如,Python 3.3引入了一个随机散列种子以防止严重的denial of service vector,这意味着即使在Python进程之间,字典顺序也会完全不同。