函数时可重复使用的代码段;提高应用的模块性和代码的重复使用率;python提供了内置的函数print();可以编写自定义函数
定义函数
规则:
函数代码块使用def关键字开头,后接函数标识符名称和圆括号。
任何传入参数和自定义变量必须放在圆括号中间
函数的第一行语句可以选择性使用文档字符串说明文字
函数内容以冒号起始,并且缩进。
return结束函数,可以有返回值,没有return的返回none
语法
def 函数名(参数列表):
函数体
实例
>>> def hello():
... print('hello china')
...
>>> hello()
hello china
带参数的函数
>>> def sum1(v1,v2):
... return v1 + v2
...
>>> sum1(1,10)
11
参数传递
python中类型术语对象,变量是没有类型的。
x = [1,2]
x = 'abc'
[1,2]是list类型,‘abc'是string类型,变量x是没有类型,仅仅代表一个对象的引用或者指针,可以是list对象,或者指向string类型的对象
python中,string,tuples,number是不可更改对象,list,dict等是可以修改的对象
不可变类型:变量赋值x=1后再赋值a=2,实际上是新生成一个int值对象10,再让a指向它,1被丢弃了,不是修改a的值,相当于新生成了a
可变类型:变量赋值lx=[1,2,3] 再赋值lx[1]=10,则将list lx的第二个元素值修改,本身x没变,是其内部的一部分值修改了。
python函数的参数传递:
不可变类型: 类似c++ 中的值传递,比如整数,字符串,元组。比如function(x),传递的只是x的值,并没有影戏那个x对象本身。如果在function(x)内部修改x的值,只是修改了另一个复制的对象,不会影响x本身。
可变类型:类似c++的引用传递,比如列表,字典。如function(lx),将lx传过去,如果修改,外部的lx将受影响
python中一切都是对戏那个,严格意义我们不能说是传值或者引用传递,我们可以称之为传不可变对象和传可变对象
python传不可变对象实例
>>> def func1(x):
... x=10
...
>>> a = 20
>>> func1(a)
>>> print(a)
20
实例中有int对象20,指向它的变量是a,在传递给函数func1时候,按照传值的方式复制了变量a,a和x都指向了同一个int对象,在x=10时候,新生成一个int值对象10,并让x指向他
传可变对象实例
>>> def func2(la):
... la.append([1,2])
... print(la)
... return
...
>>> lx = [10,20]
>>> func2(lx)
[10, 20, [1, 2]]
>>> print(lx)
[10, 20, [1, 2]]
参数
必须参数
关键字参数
默认参数
不定长参数
必需参数
必须参数需要以正确的顺序传入函数,并且调用时候数量和声名要一致
>>> def func3(a):
... print(a)
... return
...
>>> func3()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func3() missing 1 required positional argument: 'a'
>>> func3(1)
1
>>>
关键字参数
>>> def func3(s):
... print(s)
... return
...
>>> func3(s = 'hello')
hello
其中s就是关键字,如果使用关键字可以不用指定顺序
>>> func3(s = 'hello')
hello
>>>
>>>
>>>
>>> def func4(a,b):
... print(a)
... print(b)
... return
...
>>> func4(b='china',a='hello')
hello
china
默认参数
>>> def func5(a,b='china'):
... print(a)
... print(b)
... return
...
>>> func5('hello')
hello
china
不定长参数
可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数。和上述2种参数不同,声明时不会命名。格式:
def function([formal_args,] *var_args_tuple ):
function_suite
return [expression]
加了星号(*)的变量名会存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量
>>> def func6(arg1, *vartuple):
... print(arg1)
... for v in vartuple:
... print(v)
... return
...
>>> func6(100)
100
>>> func6(100,90,80)
100
90
80
匿名函数
使用lambda创建匿名函数;不再使用def语句定义函数。
lambda只是一个表达式,函数体比def简单的多
lambda主题是一个表达式,而不是一个代码块。仅仅能在其中封装有限的逻辑进去
lambda函数拥有自己的命名空间
虽然只能协议行,但不同于c++中的内联函数,后者的目的是调用小函数时不占用栈能icun从而增加运行效率
语法:
lambda [arg1 [,arg2,.....argn]]:expression
实例
>>> sum = lambda v1,v2: v1+v2
>>> print(sum(1,2)
... )
3
return语句
return[表达式]语句用于退出函数,选择性的想调用方法返回一个表达式。不带参数值得return返回none
>>> def func7(v1,v2):
... sum1 = v1 + v2
... print(sum1)
... return sum1
...
>>> a = func7(1,2)
3
>>> print(a)
3
变量作用域
python中,程序的变量并不是在哪都可以访问,访问权限决定于这个变量在哪赋值。作用于共有四种
Local 局部作用于
enclosing 闭包函数外函数中
global全局作用域
built-in 内建作用域
以上查找规则是依次扩大查找。
>>> x = int(1.3) #内建作用域
>>> g_x = 100 # 全局作用域
>>> def func9():
... e = 90 # 闭包函数外函数中
... def func10():
... l = 80 #局部作用域
...
python中只有模块-module,类-class,函数(def,lambda)才会引入新的作用域,其他的代码块(比如if/elif/else/,try/except,for/while等)是不会引入新的作用域的也就是说这些语句内定义的变量,外部可以访问,
>>> if True:
... a = 'hello'
...
>>> a
'hello'
如果在函数中就不可以了
全局变量和局部变量
在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中
global和nonlocal关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了
>>> a = 1
>>> def func11():
... global a
... print(a)
... a = 100
... print(a)
...
>>> func11()
1
100
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了
>>> def func12():
... a=10
... def func13():
... nonlocal a
... a = 100
... print(a)
... func13()
... print(a)
...
>>> func12()
100
100
看一种出错情况
>>> a = 100
>>> def func14():
... a = a+100
... print(a)
...
>>> func14()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in func14
UnboundLocalError: local variable 'a' referenced before assignment
>>>
函数的内部使用外部作用域的变量时,这个变量是只读的,是不能修改