代码改变世界

函数

2018-04-16 19:39  邪月三猩  阅读(146)  评论(0)    收藏  举报

函数的return

  1. 遇到return,结束函数。
  2. 给函数的调用者(执行者)返回值。无 return 返回None,return后面不写返回值或者写None 返回None,return 返回单个数,return 返回多个数,将多个数放在元组中返回。

函数的参数

  1. 位置参数。 形参与实参必须一一对应,按顺序传入。
  2. 以关键字的方式传入参数。必须一一对应,不分顺序。fun1(a=1,b=a)
  3. 默认参数,无论是形参还是实参必须放在位置参数的后面。
  4. 动态参数 *args,**kwargs 万能参数。在形参中是聚合参数的作用,在实参中是解包的作用。
  5. 最终的参数顺序是:位置参数,*args,默认参数,**kwargs

函数的作用域

  1. 全局作用域:全局名称空间,内置名称空间。
  2. 局部作用域:局部名称空间
  3. 变量与值的加载顺序:内置名称空间 ----> 全局名称空间----> 局部名称空间(函数执行时)
  4. 变量与值的取值顺序:局部名称空间 ---> 全局名称空间 ----> 内置名称空间

函数名的特性

  1. 可以互相赋值。
  2. 函数名可以当成函数的参数
  3. 可以当成容器类数据类型的参数
  4. 函数名可以当成函数的返回值

函数的默认参数

在 python 中,类型属于对象,变量是没有类型的:

a=[1,2,3]

a="Runoob"

以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,a仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

在 python 中,strings, tuples, 和 numbers 是不可变类型,而 list,dict 等则是可变类型。

不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,而是a指向了10。

可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

不可变类型:如 整数、字符串、元组。如fun(a),传递的只是a的copy,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。

可变类型:如 列表,字典。如 fun(la),则是将 la 的引用传过去,修改后fun外部的la也会受影响

结果如下:

传入函数的和函数返回的都是同一个对象的引用。

故:x.append会修改默认参数。

函数的默认参数应该是不可变类型的。

解决方案,使用None 作为默认值,并在函数体中增加一个对默认值的检查。

例:

上面的例子是错误的。如果传入的b是空的字符串,列表,元组,0等,任意一种bool值等于False的数据类型。也会让b=[]。

完美的解决方法是:

object()是一个内存地址,独特的私有实例,可以用这个特殊值判断用户是否提供了参数。

函数中的闭包

  1. 闭包: 内层函数对外层函数非全局变量的引用,叫做闭包
  2. 闭包的好处:如果python 检测到闭包,,函数的局部作用域不会随着函数的结束而结束
  3. 判断是不是闭包print(内层的函数名.__closure__)