Python--函数

Python--函数




什么是函数?
如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数




一、python中函数的定义和调用


(1)、函数定义
def 函数名(参数列表):
"函数_文档字符串"  #即该函数的功能说明;通过help(函数名),即可看到该函数的说明文档
函数体
return 表达式

1、函数代码块以def开头,后面紧跟的函数名和圆括号()。
2、函数名的命名规则跟变量的名字一样的,即只能是字母、数字和下划线的任何组合,但不能以数字开头,并且不能跟关键字重名。
3、函数的参数必须放在圆括号中。
4、函数内容以冒号起始,并且缩进。
5、return表达式结束,选择性地返回一个值给调用方。不带表达式的return相当于返回None。
注意:如果参数列表包含多个参数,默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配的。

实例:
def printInfo():
print('--------------------------------')
print('      人生苦短,我用Python     ')
print('--------------------------------')

(2)、函数调用
函数定义完之后,函数是 不会自动执行的,需要调用它。通过“函数名()”即可完成调用。

实例:
printInfo()

二、Python中函数的参数
(1)、函数参数的传递
#定义了能接收两个参数的函数
def add2num(a,b):
c = a + b
print(c)

#调用带参数的函数时,需要在小括号中传递数据。
add2num(11,22)

(2)、默认参数
定义函数时,可以给函数的参数设置默认值,这个参数就被称为默认参数。当调用函数的时候,由于默认参数在定义的时候已经被赋值,所以可以直接忽略,而其他参数是 必须要传入值的。如果默认参数没有传入值,则直接使用默认的值;如果默认参数传入了值,则使用传入的新值代替。
实例:
def printinfo(name,age = 20):
print('Name:', name)
print('Age:', age)

printinfo(name="miki")
printinfo(name="miki",age = 18)


结果:
Name: miki
Age: 20
Name: miki
Age: 18


注意:带有默认值的参数一定要位于参数列表的最后面,否则程序会产生异常。

(3)、不定长参数
通常在定义一个函数时,如希望函数能够处理的参数个数比当初定义的参数个数多,此时可以在函数中使用不定长参数。其基本语法格式如下:
def 函数名([formal_args,] *args,**kwargs):
"函数_文档字符串"
函数体
return 表达式

formal_args为传统定义的参数,*args和**kwargs为不定长参数。
当调用函数的时候,函数传入的参数个数会优先匹配formal_args参数的个数。如果传入的参数个数和formal_args参数的个数相同,不定长参数则会返回
空的元组或者字典;如果传入的参数个数比formal_args参数的个数多,可以分一下两种情况:
1、如果传入的参数没有直达名称,那么*args会以元组的形式存放这些多余的参数;
2、如果传入的参数指定了名称,如m=1,那么**kwargs会以字典额形式存放这些被命名的参数,如{m:1}

实例:
def test(a,b,*args):
print(a)
print(b)
print(args)

test(11,22)
>>>11
>>>22
>>>()

test(11,22,33,44,55,66,77,88,99)
>>>11
>>>22
>>>(33,44,55,66,77,88,99)


如果在参数列表的末尾使用两个星号(*)表示参数,代码如下:
def test(a,b,*args,**kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11,22,33,44,55,66,77,88,99)
>>>11
>>>22
>>>(33,44,55,66,77,88,99)
>>>{}

从上述结果可知,如果在调用test函数时传入多个数值,这些数值会从左向右依次匹配函数test定义时的参数,如果传统的参数匹配够了,多余的参数会组成一个元组,和不定长参数args进行匹配。那什么情况下,传入的数据会匹配参数kwargs呢?

test(11,22,33,44,55,66,77,m=88,n=99)
>>>11
>>>22
>>>(33,44,55,66,77)
>>>{'m':88,'n':99}


结论:不定长参数传递的个数可以大于定义函数时的参数数目。如果传入的参数没有名字,那么传入的值会给args变量;如果传入的参数有名字,那么传入的值会给kwargs变量。




三、函数的返回值
所谓“返回值”,就是程序中的函数完成一件事后,最后给调用者的结果。
def add2num(a,b):
c = a + b
return c
或者
def add2num(a,b):
return a + b

函数add2num中包含return语句,意味着这个函数有一个返回值,其值就是a和b相加的结果。



四、函数的四种类型
1、函数无参数,无返回值
2、函数无参数,有返回值
3、函数有参数,无返回值
4、函数有参数,有返回值



五、变量作用域
1、LEGB原则
Python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。看下面一段代码:
>>>a = 10
>>>def test():
... a = 20
... print('a的值是%d'%a)
...
>>>test()
a的值是20

上述代码有两个变量a,当在test函数中输出变量a的值时,为什么输出的是20,而不是10呢?其实,这就是变量作用域不同导致的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4中,如下。
L(Local):函数内的区域,包括局部变量和形参。
E(Enclosing):外面嵌套函数区域,常见的是闭包函数外的函数。
G(Global):全局作用域。
B(Built-in):内建作用域。
Python中变量是采用L->E->G->B的规则查找的,即Python检索变量的时候,先是在局部变量中查找,如果找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

2、全局变量和局部变量

    2.1 局部变量



总结:
局部变量,就是在函数内部定义的变量
不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响
局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用


    2.2 全局变量
如果一个变量,即能在一个函数中使用,也能在其他的函数中使用,这样的函数就是全局变量。
#定义全局变量
a = 100
def test1():
print(a)
def test2():
print(a)
test1()
test2()
>>>100
>>>100

思考:如果全局变量和局部变量名字一样,会用谁呢?

    

    既然全局变量,就是能够在所有的函数中进行使用,那么可否进行修改呢?


总结:
在函数外边定义的变量叫做全局变量
全局变量能够在所有的函数中进行访问。
如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错。
如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的。



2.3可变类型的全局变量
>>> a = 1
>>> def f():
...     a += 1
...     print a
...
>>> f()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 2, in f
UnboundLocalError: local variable 'a' referenced before assignment
>>>
>>>
>>> li = [1,]
>>> def f2():
...     li.append(1)
...     print li
...
>>> f2()
[1, 1]
>>> li
[1, 1]

总结:
在函数中不使用global声明全局变量时,不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据。
对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使global时无法修改全局变量。
对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可以修改全局变量。





六、匿名函数
简单的说,匿名函数就是没有名称的函数,也就是不在使用def语句定义的函数。如果要声明匿名函数,则需要使用lambda关键字,
匿名函数的声明格式如下:
lambda [arg1 [,arg2,...argn]]:expression
上述格式中,“[arg1 [,arg2,...argn]]”表示的是函数的参数,“expression”表示的是函数的表达式。

实例1:
sum = lambda arg1, arg2: arg1 + arg2
        print "Value of total : ", sum( 10, 20 )
        print "Value of total : ", sum( 20, 20 )
>>>Value of total :  30
        >>>>Value of total :  40

需要注意的是,使用lambda声明的匿名函数能接收任何数量的参数,但是只能返回一个表达式的值。

实例2:
#匿名函数作为函数参数传递
>>> def fun(a, b, opt):
...     print "a =", a
...     print "b =", b
...     print "result =", opt(a, b)
...
>>> fun(1, 2, lambda x,y:x+y)
a = 1
b = 2
result = 3

实例3:
#匿名函数作为内置函数的参数使用
stus = [
{"name":"zhangsan", "age":18}, 
{"name":"lisi", "age":19}, 
{"name":"wangwu", "age":17}
]

#按name排序
>>> stus.sort(key = lambda x:x['name'])
>>> stus
[{'age': 19, 'name': 'lisi'}, {'age': 17, 'name': 'wangwu'}, {'age':18, 'name': zhangsan}]

#按age排序
[{'age': 17, 'name': 'wangwu'}, {'age': 18, 'name': 'zhangsan'}, {'age':19, 'name': lisi}]




总结:
与def相比,lambda创建的函数有很多不同的地方。
1、def创建的函数是有名称的,而lambda没有函数名称。
2、lambda返回的结果通常是一个对象或者一个表达式,它不会将结果赋给一个变量,而def可以。
3、lambda只是一个表达式,函数体比def简单很多,而def是一个语句。
4、lambda表达式的冒号后面只能有一个表达式,def则可以有多个。
5、像if或for等语句不能用于lambda中,def则可以。
6、lambda一般用来定义简单的函数,而def可以定义复杂的函数。
7、lambda函数一般不能共享给别的程序调用,def可以。







猜你喜欢

转载自blog.csdn.net/zhubao124/article/details/79691617