这是我参与更文挑战的第5天,活动详情查看: 更文挑战
函数的出现是为了提高应用的模块性,和代码的重复利用率。
1.概念
函数标准结构如下:
def <函数名> (<函数参数>): <代码块> return <返回表达式,可不返回>
2.参数传递
2.1 变量&对象
在python
中,变量是没有类型,只有对象有类型
a = 'stone' list= [1,2,3]
上面代码中,'stone'
是String
类型,[1,2,3]
是List
类型,而变量a
和list
只是对一个对象的应用,相当于C语言中的指针,也就是说,a
可以指向一个String
类型,可以指向List
类型,也可以指向其它类型。
2.2 可变对象和不可变对象
python变量保存的是对象的引用,这个引用指向堆内存里的对象,在堆中分配的对象分为两类,一类是可变对象,一类是不可变对象。
众所周知,Python3
的六个标准对象类型中:
- 不可变对象类型(3 个):Number(数字)、String(字符串)、Tuple(元组);
- 可变对象类型(3 个):List(列表)、Dictionary(字典)、Set(集合)。
对于不可变对象,即变量指向的内存的中的值不能够被改变
int_val=5 int_val=10
如上两行代码,第一行代码让变量int_val
指向堆上新开辟的空间整数5,第二行代码在堆上开辟新的空间存储整数10,让变量int_val
指向新开辟的空间,原来存储整数5堆空间的内容没有改变,这即是不可变
可通过内置函数id(int_val)
打印两次内存空间地址,可以看到两次地址值不一样
对于可变对象,即变量指向的内存的中的值能够被改变
list_val=[1,2,3] list_val[1]=4
如上两行代码,列表list_val
可改变,直接改变指向的内存中的值,没开辟新空间,这即是可变
可通过内置函数id(list_val)
打印两次内存空间地址,可以看到两次地址值是不一样
2.3函数传参
python
规定参数传递都是传递引用,也就是传递给函数的是原变量实际所指向的内存空间,修改的时候就会根据该引用的指向去修改该内存中的内容。
通过以下的代码讲解:
```
函数体修改参数内容
def valchange(intval,strval,listval): intval = intval+1 strval = strval + 'd' listval[1] = 1 return intval, strval, listval ```
```
调用函数
inta = 1 stra = 'ac' lista = [0, 0] [intb, strb, listb] = valchange(inta, stra, lista) print('inta = ', inta) print('intb = ', intb) print('stra = ', stra) print('strb = ', strb) print('lista = ', lista) print('listb = ', listb) ```
输出结果
int_a = 1 int_b = 2 str_a = ac str_b = acd list_a = [0, 1] list_b = [0, 1]
通过上面例子,可以得出结论:
- 对于函数参数是不可变对象,函数体对该对象的修改时,修改的是复制的对象,不会影响函数外部的参数
- 对于函数参数是可变对象,函数体对该对象的修改会直接影响到函数外部的参数
3.迭代器和生成器
3.1迭代器
迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
使用方式
iter(<可迭代对象>)
创建迭代器对象,可迭代对象包括字符串,列表或元组对象,或者自定义迭代对象next(<迭代器对象>)
,迭代器的下一个元素
具体使用步骤:
list =[1,2,3] iterator = iter(list) # 创建跌迭代器对象 print(next(iterator)) # 打印迭代器的下一个元素,输出1
注意
使用内置函数next()
,可能出现StopIteration
异常,这个异常用于标识迭代的完成,防止出现无限循环的情况。
自定义迭代器对象
把一个类作为一个迭代器使用需要在类中实现两个方法__iter__()
与 __next__()
3.2生成器
使用了 yield 的函数被称为生成器,生成器是一个返回迭代器的函数,只能用于迭代操作,可以理解为生成器就是迭代器。调用一个生成器函数,返回的是一个迭代器对象。
原理
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行
使用方式
见如下代码
```
自定义一个支持浮点数的rangedef custom_range(start,end,step): x = start while x < end: yield x x += step
```
```
使用生成器,与用迭代器无异for i in range(1,10,0.5): print(i)
```
4.lambda
使用 lambda 来创建匿名函数
使用方式
```
不使用lambdadef add(x,y): return x+y
```
```
使用lambdaadd=lambda x,y:x+y
```
5.作用域
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。global
关键字申明使用全局作用于的变量。
通过以下例子讲解:
count = 0 #全局变量index = 0 #全局变量def count_num(): global count#全局变量 count += 1 index = 2#局部变量 print('in function ', count, index) count_num()print('out function ', count, index)
输出
in function 1 2out function 1 0