list.append如何工作?

时间:2017-02-20 01:37:48

标签: python

 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的方法append只接受一个参数,为什么不在方法show的定义中检测行alist.append(*args, **kwargs)上的语法错误?

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分:1)

Python对象是强类型的。绑定到它们的名称不是。函数参数也不是。鉴于Python的动态特性,静态预测给定源位置的变量在执行时的类型是非常困难的,因此一般规则是Python不会费心去尝试。

在您的具体示例中,alist不在本地范围内。因此,可以在执行函数定义后修改,并且您的函数可以看到更改,参见下面的代码片段。 因此,符合一般规则:当您致电alist时,预测.append是否会成为一个列表?几乎不可能。特别是,解释器无法预测这将是一个错误。

以下是一些代码,只是为了推动归属,即在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]

答案 2 :(得分:0)

这不是语法错误,因为它是在运行时解决的。在解析期间最初会捕获语法错误。像无法匹配的括号,未定义的变量名,缺少参数(这不是缺少的参数* args意味着任意数量的参数)。

show无法知道您在运行时传递的内容,因为您在args内扩展show变量,可能会有任意数量的参数进入这是有效的语法! 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)