【发布时间】:2013-09-03 13:16:20
【问题描述】:
假设我定义了以下类:
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 如何确定该抱怨哪一个?
【问题讨论】:
-
附带说明,类构造函数调用的工作方式与调用函数(或方法)完全相同,因此您可以稍微简化测试。
-
@abarnert 是吗?我得到:
def my_func(x, y): pass,然后my_func(i=2, a=1)抱怨'i',而MyClass(i=2, a=1)抱怨'a'。 -
如@MartijnPieters 的回答中所述,行为未定义。因此,实际测试的结果不一定有用或适用。
-
是的。使用
dis模块查看字节码,您会发现两者都使用CALL_FUNCTION。(另外请注意,由于python 不是静态类型的,解释器无法区分一个类/callable/function 直到 开始执行调用)。另请注意,__init__方法有一个 self 参数。如果你用def __init__(self, x): pass定义一个类,那么它会再次抱怨i。似乎函数的参数数量很重要。
标签: python