Q1 函数是一等对象
A1
- 函数可以作为参数传递
- 可以返回函数
- 可以赋值给变量
- 其表现称得上对象
Q2 函数的参数
A2 有位置参数、关键字参数(默认参数)、可变参数(元组参数, *args
)以及字典参数( **kargs
)。其中元组参数和字典参数名称是我自己取的,网上各种叫法都有,我是根据其数据结构特点取名的。可变参数是指就是一个元组,里面可以存放0个或多个参数,使用*
标志。字典参数是在Python3中新加的,其数据结构表现与字典类似,使用**
标志。
Q3 传值还是传引用
A3 比较有争议,see: https://www.zhihu.com/question/20591688
我倾向于Python里面没有传值和传引用一说,因为Python没有这两个概念。如果我们从表现的像鸭子即可以认为是鸭子的观点看,对于不可变对象作为函数参数,相当于C++的值传递;对于可变对象作为函数参数,相当于C++的引用传递。但实际上这个理解非常肤浅。这个问题有关Python的名称绑定机制(name binding)。如果按名称绑定的观点看,传进去的就是一块函数外的数据,形参变量名称与这块数据绑定,没有数据被复制,可以认为是引用传递(但实际上又没有指针这个概念,所以讨论到底属于传值还是传引用是没有意义,有意义的地方在于理解参数传递过程以及名称绑定机制)
Python中变量是由名称+数据
构成,如果使用一个仅有名称而无数据的变量(或许不该叫变量)会报NameError:name ‘xxx’ is not defined. 数据是有类型的而名称没有类型。名称和数据可以分离,这个过程必然伴随,名称与其它数据结合。而在C/C++这样的语言中名称是不能与数据分离的,名称即数据。
名称与数据的第一次绑定过程,即为名称的定义(名称的初始化)。类似于像a, b = b, a
这样的变戏法就是一个名称的重新绑定过程,没有新的数据被创建,因此也不需要另外一个名称。如果从有没有新的数据被创建角度观察Python行为,也许很多疑惑就能解开,比如期待被修改的数据没有被修改,不期待修改的数据被修改。
1 | a = [0, [1, 2, 3], 4, 5] |
Q4 嵌套函数
A4 这是一个比较大的话题,主要讨论变量作用域