1、什么是函数?
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
2、为什么使用函数?
函数能提高应用的模块性,和代码的重复利用率。
你已经知道Python提供了许多内建函数,比如print()。
但你也可以自己创建函数,这被叫做用户自定义函数。
3、函数的特性
1)代码重用
2)保持一致性
3)可扩展性
4、函数的创建
定义函数使用 def关键字,一般格式如下:#def 函数名(参数列表):#函数体
defhello():'''我是描述信息:描述该函数是干什么用的'''
print('hello')
hello()#调用
print(hello.__doc__) #通过 hello.__doc__ 查看描述
'''hello
描述信息,描述该函数是干什么用的'''
优雅取代多分支 if
deffoo():print('foo')defbar():print('bar')
dic={'foo':foo,'bar':bar,
}whileTrue:
choice=input('>>:').strip()if choice indic:
dic[choice]()
5、函数名的命名规则
a、函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
b、函数名是区分大小写的。
c、函数名不能是保留字。
6、函数的调用
#语句形式: foo() 或 m=foo() 会执行函数 foo,并输出屏幕
deffoo():print('foo')
foo()
m=foo()'''foo
foo'''
#表达式形式:res=10*my_sum(1,2),先执行函数,如果有 print 就输出屏幕,并把函数结果*10赋值给 res
defmy_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:importtime
times=time.strftime('%Y--%m--%d')deff(times):print('Now time is : %s'%times)
f(times)
例3:defshow_shopping_car():
saving= 1000000shopping_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=0for i inshopping_car:
expense+= i[1]print('\n您的余额为 %s' % (saving-expense))
show_shopping_car()'''********************您已经购买的商品如下********************
1: ('Mac', 9000)
2: ('kindle', 800)
3: ('tesla', 100000)
4: ('Python book', 105)
您的余额为 890095'''
1:形参和实参例子
defaction1(n):print('starting action1...')
with open('日志记录', 'a') as f:
f.write('end action%s\n' %n)defaction2(n):print('starting action2...')
with open('日志记录', 'a') as f:
f.write('end action%s\n' %n)defaction3(n):print('starting action3...')
with open('日志记录', 'a') as f:
f.write('end action%s\n' %n)
action1(1)
action2(2)
action3(3)'''starting action1...
starting action2...
starting action3...
打开文件查看
end action1
end action2
end action3'''
#***************代码重用#上面发现每个函数都有打开文件,写内容的重复代码,把这些代码提取出来
deflogger(n):
with open('日志记录', 'a') as f:
f.write('end action%s\n' %n)defaction1():print('starting action1...')
logger(1)defaction2():print('starting action2...')
logger(2)defaction3():print('starting action3...')
logger(3)
action1()
action2()
action3()'''starting action1...
starting action2...
starting action3...
打开文件查看
end action1
end action2
end action3'''
#***************可扩展和保持一致#再不改变各个 action 函数内部的前提下额外为日志加上时间
importtimedeflogger(n):
time_format= '%Y-%m-%d %X'time_current=time.strftime(time_format)
with open('日志记录', 'a') as f:
f.write('%s end action%s\n' %(time_current, n))defaction1():print('starting action1...')
logger(1)defaction2():print('starting action2...')
logger(2)defaction3():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'''
2:一个例子来说明函数的三个特性
b、位置参数(必备参数)
位置参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
deff(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 解释器能够用参数名匹配参数值。
deff(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种参数不同,声明时不会命名。
*argsdef add(*args): #args 内部是一个元祖
sum =0for v inargs:
sum+=vreturnsumprint(add(1, 4, 6, 9)) #20
print(add(1, 4, 6, 9, 5)) #25
加了星号(*)的变量名会存放所有未命名的变量参数(值)。而加(**)的变量名会存放命名的变量参数(键值)**kwargsdef print_info(**kwargs): #kwargs 内部是一个字典
for i inkwargs:print('%s:%s' % (i, kwargs[i])) #根据参数可以打印任意相关信息了
returnprint_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 inkwargs: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 相当于关键字参数
*argsdef 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:defadd(x, y, f):return f(x) +f(y)
res= add(3, -6, abs) #abs 函数作为参数传递
print(res)例2:deffoo():
x= 3
defbar():returnxreturn bar #返回函数名:一个内存地址,也是函数的本质
print(foo)print(foo())例3:deff(n):return n*ndeffoo4(a, b, func):
ret= func(a)+func(b)returnretprint(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)
deff():print('ok')return True #作用:1:结束函数;2:返回某个对象
f()deffoo():return 1,'alex',8
print(foo()) #(1, 'alex', 8),多个对象组装成一个元组,可以用多个变量去接收
.