1、什么是函数?
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
2、为什么使用函数?
函数能提高应用的模块性,和代码的重复利用率。
你已经知道Python提供了许多内建函数,比如print()。
但你也可以自己创建函数,这被叫做用户自定义函数。
3、函数的特性
1)代码重用
2)保持一致性
3)可扩展性
4、函数的创建
定义函数使用 def 关键字,一般格式如下: # def 函数名(参数列表): # 函数体 def hello(): '''我是描述信息:描述该函数是干什么用的''' print('hello') hello() # 调用 print(hello.__doc__) # 通过 hello.__doc__ 查看描述 ''' hello 描述信息,描述该函数是干什么用的 '''
优雅取代多分支 if
def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input('>>: ').strip() if choice in dic: dic[choice]()
5、函数名的命名规则
a、函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
b、函数名是区分大小写的。
c、函数名不能是保留字。
6、函数的调用
# 语句形式: foo() 或 m=foo() 会执行函数 foo,并输出屏幕 def foo(): print('foo') foo() m = foo() ''' foo foo ''' # 表达式形式:res=10*my_sum(1,2),先执行函数,如果有 print 就输出屏幕,并把函数结果*10赋值给 res def my_sum(a, b): print('test') return a+b res = 10*my_sum(1, 2) print(res) ''' test 30 test ''' # 函数调用作为另外一个函数的参数:print(my_sum(1,2)) print(my_sum(1, 2)) # 3
7、函数的参数
a、形参和实参
形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
理解:实参本质是形参变量名的值,形参本质是变量名
注意:实参不要传递可变的数据类型,因为在函数里,函数可以对实参进行修改,从而影响全局变量
例1: def f(x): #形参 print(x) f(3) # 实参 例2: import time times=time.strftime('%Y--%m--%d') def f(times): print('Now time is : %s'%times) f(times) 例3: def show_shopping_car(): saving = 1000000 shopping_car = [ ('Mac', 9000), ('kindle', 800), ('tesla', 100000), ('Python book', 105), ] print('您已经购买的商品如下'.center(50, '*')) for i, v in enumerate(shopping_car, 1): print('%s: %s' % (i, v)) expense = 0 for i in shopping_car: expense += i[1] print(' 您的余额为 %s' % (saving-expense)) show_shopping_car() ''' ********************您已经购买的商品如下******************** 1: ('Mac', 9000) 2: ('kindle', 800) 3: ('tesla', 100000) 4: ('Python book', 105) 您的余额为 890095 '''
def action1(n): print('starting action1...') with open('日志记录', 'a') as f: f.write('end action%s ' % n) def action2(n): print('starting action2...') with open('日志记录', 'a') as f: f.write('end action%s ' % n) def action3(n): print('starting action3...') with open('日志记录', 'a') as f: f.write('end action%s ' % n) action1(1) action2(2) action3(3) ''' starting action1... starting action2... starting action3... 打开文件查看 end action1 end action2 end action3 ''' # ***************代码重用 # 上面发现每个函数都有打开文件,写内容的重复代码,把这些代码提取出来 def logger(n): with open('日志记录', 'a') as f: f.write('end action%s ' % n) def action1(): print('starting action1...') logger(1) def action2(): print('starting action2...') logger(2) def action3(): print('starting action3...') logger(3) action1() action2() action3() ''' starting action1... starting action2... starting action3... 打开文件查看 end action1 end action2 end action3 ''' # ***************可扩展和保持一致 # 再不改变各个 action 函数内部的前提下额外为日志加上时间 import time def logger(n): time_format = '%Y-%m-%d %X' time_current = time.strftime(time_format) with open('日志记录', 'a') as f: f.write('%s end action%s ' % (time_current, n)) def action1(): print('starting action1...') logger(1) def action2(): print('starting action2...') logger(2) def action3(): print('starting action3...') logger(3) action1() action2() action3() ''' starting action1... starting action2... starting action3... 打开文件查看 2018-05-02 12:03:39 end action1 2018-05-02 12:03:39 end action2 2018-05-02 12:03:39 end action3 '''
b、位置参数(必备参数)
位置参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
def f(name, age): print('I am %s,I am %d' % (name, age)) f('alex', 18) f('alvin', 16) # 位置参数,按函数提供的顺序,传递参数 ''' I am alex,I am 18 I am alvin,I am 16 '''
c、关键字参数(实参参数)
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def f(name, age): print('I am %s,I am %d' % (name, age)) # f(16, 'alvin') # 报错:TypeError: %d format: a number is required, not str f(age=16, name='alvin') # 关键字参数,指定 age 和 name 的值 ''' I am alvin,I am 16 '''
d、缺省参数(默认参数)
调用函数时,缺省参数的值如果没有传入,则被认为是默认值。下例如果sex没有被传入,会打印默认的sex。
默认参数一定要放在位置参数后面
def print_info(name, age, sex='male'): # 性别的默认值为 male,下面传递的时候可以改 print('Name:%s' % name) print('age:%s' % age) print('Sex:%s' % sex) print_info('hjc', 24, 'fmale') # 上面定义的 male ,这里传递参数可以改 print_info('hjc', 24) # 没有传递 sex 的参数,默认会显示 sex 的默认值 ''' Name:hjc age:24 Sex:fmale Name:hjc age:24 Sex:male '''
e、不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。
*args def add(*args): # args 内部是一个元祖 sum = 0 for v in args: sum += v return sum print(add(1, 4, 6, 9)) # 20 print(add(1, 4, 6, 9, 5)) # 25 加了星号(*)的变量名会存放所有未命名的变量参数(值)。而加(**)的变量名会存放命名的变量参数(键值) **kwargs def print_info(**kwargs): # kwargs 内部是一个字典 for i in kwargs: print('%s:%s' % (i, kwargs[i])) # 根据参数可以打印任意相关信息了 return print_info(name='alex', age=18, sex='female', hobby='girl',nationality='Chinese', ability='Python') ''' name:alex age:18 sex:female hobby:girl nationality:Chinese ability:Python '''
不定长参数位置说明
关于不定长参数的位置:*args 放在左边,**kwargs 参数放在右边
def info(*args, **kwargs): # 位置固定死了,反过来会报错 print('args:', args) print('kwargs:', kwargs) for i in kwargs: print('%s:%s' % (i, kwargs[i])) info('hjc', 24, 'male', job='IT', hobby='girls', height=100) ''' args: ('hjc', 24, 'male') kwargs: {'job': 'IT', 'hobby': 'girls', 'height': 100} job:IT hobby:girls height:100 ''' # def print_info(name,**kwargs,*args):报错 def print_info(name, *args, **kwargs): print('Name:%s' % name) print('args:', args) print('kwargs:', kwargs) print_info('alex', 18, hobby='girl', nationality='Chinese', ability='Python') ''' Name:alex args: (18,) kwargs: {'hobby': 'girl', 'nationality': 'Chinese', 'ability': 'Python'} ''' # print_info(hobby='girl', 'alex', 18, nationality='Chinese', ability='Python') # 报错 # print_info('alex', hobby='girl', 18, nationality='Chinese', ability='Python') # 报错
注意,还可以这样传参:
*args 相当于位置参数
**kwargs 相当于关键字参数
*args
def f(*args): print(args) f(*[1, 2, 5]) # 传递一个列表,(1, 2, 5) f(*(1, 2, 5)) # 传递一个元组(1, 2, 5)
**kwargs
方式1:
def f(**kargs): print(kargs) f(**{'name': 'alex'}) # {'name': 'alex'} 方式2: def f2(**kwargs): print(kwargs) f2(info={'name': 'alex'}) # {'info': {'name': 'alex'}}
8、高阶函数
高阶函数是至少满足下列一个条件的函数:
1、接受一个或多个函数作为输入,也就是把函数名作为参数输入
2、函数名可以作为返回值
例1: def add(x, y, f): return f(x) + f(y) res = add(3, -6, abs) # abs 函数作为参数传递 print(res)
例2: def foo(): x = 3 def bar(): return x return bar # 返回函数名:一个内存地址,也是函数的本质 print(foo) print(foo())
例3: def f(n): return n*n def foo4(a, b, func): ret = func(a)+func(b) return ret print(foo4(1, 2, f)) ''' 解释: 先定义一个函数 f,函数 f 的对象是 n*n 定义 foo4 函数,形参是(a,b,func) print(foo4(1,2,f)) 这里的 f,作为 foo4 的形参,func 调用函数 f,f(a)=f(1*1)=1,f(b)=f(2*2)=4 ret=1+4 '''
9、函数返回值
要想获取函数的执行结果,就可以用return语句把结果返回
注意:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
- 如果未在函数中指定return,那这个函数的返回值为None
- return 多个对象,解释器会把这多个对象组装成一个元组作为一个整体结果输出。可以通过变量压缩去取元组中的值
- 通常无参函数不需要给 return 返回值
- return 只有一个对象,返回的就是这个对象
- 变量压缩:tuple=(1,2,3)————a,b,c=(1,2,3)
def f(): print('ok') return True # 作用:1:结束函数;2:返回某个对象 f() def foo(): return 1,'alex',8 print(foo()) # (1, 'alex', 8),多个对象组装成一个元组,可以用多个变量去接收
.