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变量。

(4)、拆包

def salary_comp(basic_money,*other_money,**proportion):
    print("缴费基数:{}".format(basic_money))
    print("其他工资:{}".format(other_money))
    print("比例:{}".format(proportion))

other_money = (500,200,100,1000)
proportion_dict = {"e":0.2,"m":0.1,"a":0.12}

salary_comp(8000,other_money,proportion_dict) #未使用拆包
salary_comp(8000,*other_money,**proportion_dict)

缴费基数:8000
其他工资:((500, 200, 100, 1000), {'e': 0.2, 'm': 0.1, 'a': 0.12})
比例:{}

缴费基数:8000
其他工资:(500, 200, 100, 1000)
比例:{'e': 0.2, 'm': 0.1, 'a': 0.12}


三、函数的返回值
所谓“返回值”,就是程序中的函数完成一件事后,最后给调用者的结果。

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()
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()
li

[1, 1]
[1, 1]

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

 

可变类型 Vs 不可变类型

可变类型(mutable):列表,字典

不可变类型(unmutable):数字,字符串,元组

这里的可变不可变,是指内存中的那块内容(value)是否可以被改变



六、匿名函数
简单的说,匿名函数就是没有名称的函数,也就是不在使用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:

sum = lambda x,y:x+y
print(sum(10,20))
30

实例3:
#匿名函数作为函数参数传递

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

实例4:
#匿名函数作为内置函数的参数使用

stus = [
{"name":"zhangsan", "age":18}, 
{"name":"lisi", "age":19}, 
{"name":"wangwu", "age":17}
]

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

#按age排序
stus.sort(key = lambda x:x['age'])
print(stus)
[{'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可以。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值