2017-02-20 91 views
1
alist = [] 
def show(*args, **kwargs): 
     alist.append(*args, **kwargs) 
     print(alist) 


>>> show('tiger') 
['tiger'] 
>>> show('tiger','cat') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (2 given) 
>>> show('tiger','cat', {'name':'tom'}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (3 given) 

由于alist的追加方法只接受一个参数,为什么不检测方法show的定义中的线alist.append(*args, **kwargs)上的语法错误?list.append是如何工作的?

+1

因为这不是蟒蛇是如何工作的..它没有任何语法错误,功能就是这样不能接受超过1个参数。尝试list.extend – user2682863

+6

翻译者应该如何知道在你打电话给show的时候'alist'会是什么? – TigerhawkT3

+0

你是不是故意问为什么show('tiger')没有错误,但是show('tiger','cat')'? –

回答

2

这不是语法错误,因为语法非常好,而且函数可能会也可能不会引发错误,具体取决于您如何调用它。

你调用它的方式:

alist = [] 
def show(*args, **kwargs): 
    alist.append(*args, **kwargs) 
    print(alist) 

>>> show('tiger') 
['tiger'] 
>>> show('tiger','cat') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (2 given) 

一种不同的方式:

alist = [] 
def show(*args, **kwargs): 
    alist.append(*args, **kwargs) 
    print(alist) 

>>> show('tiger') 
['tiger', 'tiger'] 
>>> class L: pass 
... 
>>> alist = L() 
>>> alist.append = print 
>>> show('tiger','cat') 
tiger cat 
<__main__.L object at 0x000000A45DBCC048> 
0

它不是一个语法错误,因为它在运行时解决。如果您愿意,语法错误最初会在解释时被捕获。像无与伦比的括号,未定义的变量名称,缺少的参数(这不是缺少的参数*参数意味着任意数量的参数)。

show无法知道什么,你会在运行时传递的方式,因为你正在扩大内部showargs变量,可以有任意数量的进来参数,它是有效的语法! list.append需要一个参数!一个tuple,一个list,一个int,字符串,自定义类等等。您传递的是一些数字元素,具体取决于输入上的。如果你删除了*,则它是全部花钱的,因为它的一个元件,例如, alist.append(args)

这一切意味着您的show功能有问题。只有当它的长度为1时,它才能处理args。如果它的0也在append处得到TypeError被调用。如果它不止是它的破碎,但你不会知道,直到你用不好的输入来运行它。

您可以遍历args(和kwargs)中的元素并逐个添加它们。

alist = [] 
def show(*args, **kwargs): 

    for a in args: 
     alist.append(a) 
    for kv in kwargs.items(): 
     alist.append(kv) 

    print(alist) 
1

Python对象是强类型的。绑定到他们的名字不是。函数论证也不是。鉴于Python的动态特性,静态地预测给定源位置的变量类型在执行时会非常困难,所以一般规则是Python不会尝试。

在您的具体示例中,alist不在本地范围内。因此,可以在执行之后修改,并且您的函数可以看到更改,请参阅参考资料。下面的代码片段。 因此,根据一般规则:当您拨打.append时,预测alist是否会成为列表?几乎不可能。特别是,解释者无法预测这将是一个错误。

这里有一些代码只是为了说明静态类型检查在Python中是不可能实现的。它使用非本地变量,如你的例子。

funcs = [] 
for a in [1, "x", [2]]: 
    def b(): 
     def f(): 
      print(a) 
     return f 
    funcs.append(b()) 

for f in funcs: 
    f() 

输出:

[2] # value of a at definition time (of f): 1 
[2] # value of a at definition time (of f): 'x' 
[2] # value of a at definition time (of f): [2] 

同样地,对于非全球非本地变量:

funcs = [] 
for a in [1, "x", [2]]: 
    def b(a): 
     def f(): 
      print(a) 
     a = a+a 
     return f 
    funcs.append(b(a)) 

for f in funcs: 
    f() 

输出:

2  # value of a at definition time (of f): 1 
xx  # value of a at definition time (of f): 'x' 
[2, 2] # value of a at definition time (of f): [2]