Python函数 - littleboy12580/learning_python GitHub Wiki

函数

作用域

  • 作用域可以分为本地作用域与全局作用域
  • 内嵌的模块是全局作用域
  • 全局作用域的作用范围仅限于单个文件
  • 在原处改变对象并不会把变量划分为本地变量,只有对变量名赋值才可以;例如L.append(X)语句不会将L划分为本地变量,而L = X却可以。

变量的LEGB作用域查找原则

当引用一个变量时,Python会按以下顺序依次进行查找:首先是在本地变量中查找,然后在任意上层函数作用域里查找,再然后是全局作用域,最后则是在内置作用域查找。

global语句

通过global声明可以将一个变量变为全局变量

X = 88
def func():
    global X
    X = 99
func()
print(X)

此时X值为99

文件间的调用修改

在导入模块之后,被导入模块的全局变量属性是可能会被修改的,如下例:

#first.py
X=99
#second.py
import first
print(first.X)
first.X = 88

这种文件依赖性过强的情况会导致代码不灵活,因此在文件间通信最好的办法是通过调用函数,传递参数,然后得到其返回值,如下例:

#first.py
X=99
def setX(new):
    global X
    X = new
#second.py
import first
first.setX(88)

参数的引用

python中函数参数是通过赋值传递的,函数中的参数名可以在调用时通过变量实现共享对象;因此函数中的可变对象参数的原处修改是可以影响到调用者的,就相当于C语言里的指针传递一样;而不可变对象参数即使进行了原处修改也不会影响到调用者,相当于值传递。

参数的匹配扩展

参数收集

参数收集有两种,*

*在函数定义中表示在元组中收集不匹配的位置参数

def f(*args): print(args)
f(1)
f(1,2,3,4)

上面代码最后输出的是(1,)和(1,2,3,4)

**在函数定义中只对关键字参数有效,它将关键字参数传递给一个新的字典

def f(**args): print(args)
f(a=1,b=2)

上面代码最后输出的是{'a':1,'b':2}

函数头部能够混合一般参数,*参数以及**参数来实现更加灵活的调用方式

def f(a,*pargs,**kargs): print(a,pargs,kargs)
f(1,2,3,x=1,y=2)

上面代码最后输出的是 1 (2,3) {'y':2,'x':1}

解包参数

与参数收集相对应,在调用参数的时候也能够使用*和**语法,此时是将传入的参数解包成不同的参数

def func(a,b,c,d): print(a,b,c,d)
args = (1,2,3,4)
func(*args)

上面代码结果为1 2 3 4

args = {'a':1,'b':2,'c':3,'d':4}
func(**args)

上面代码结果为 1 2 3 4

func(*(1,2),**{'d':4,'c':4})
func(1,c=3,*(2,),**{'d':4})

上面代码结果为1 2 4 4和1 2 3 4

参数排序规则

在一个函数头部,keyword-only参数必须编写在**args之前,*args之后

lambda表达式

lambda表达式创建了一个之后能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给了一个变量名。

f=lambda x,y,z:x+y+z
f(2,3,4)

默认参数也能够在lambda参数中使用

x=(lambda a="fee",b="fie",c="foe":a+b+c)
x("wee")

输出为'weefiefoe'

生成器函数

  • 送回一个值并随后从其退出的地方继续的函数叫做生成器函数;它通过yield表达式來挂起函数并向调用者发送回一个值,但是保留足够的状态以使得函数能够从它离开的地方继续。
  • 生成器函数返回的是生成器对象,他支持迭代器协议,存在__next__()方法
def gensquares(N):
    for i in range(N):
        yield i ** 2
for i in gensquares(5):
    print(i,end=' : ')

最后的输出为 0 : 1 : 4 : 9 : 16 :

  • 生成器表达式:与列表解析类似不过是括在圆括号中而不是方括号中
(x ** 2 for x in range(4))

返回的是一个可迭代对象而不是列表

  • 生成器函数与生成器表达式均支持自动迭代和手动迭代,手动迭代需要使用iter()函数来启动迭代,然后使用next()进行迭代

  • 生成器是单迭代对象

解析表达式

python3.0中可用的4种解析表达式形式:列表解析,生成器表达式,集合解析以及字典解析

  • 列表解析
[x * x for x in range(10)]
  • 生成器表达式
(x * x for x in range(10))
  • 集合解析
{x * x for x in range(10)}
  • 字典解析
{x:x * x for x in range(10)}