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、形参和实参

形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)

实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参

区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参

理解:实参本质是形参变量名的值,形参本质是变量名

注意:实参不要传递可变的数据类型,因为在函数里,函数可以对实参进行修改,从而影响全局变量

函数的调用过程python python函数调用过程的特点_函数调用

函数的调用过程python python函数调用过程的特点_日志记录_02

例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:形参和实参例子

函数的调用过程python python函数调用过程的特点_函数调用

函数的调用过程python python函数调用过程的特点_日志记录_02

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),多个对象组装成一个元组,可以用多个变量去接收

.