1.定义函数
函数的特性
1.减少重复代码
2.使程序变得可扩展
3.使程序变得易维护
关键字def,define
def greet_user(): print('Hello!') greet_user()
2.向函数传递信息
def greet_user(username): print('Hello!'+username.title()+'!') greet_user('jesse')
3.实参和形参
上述代码,greet_user()是形参,'jesse'是实参
形参:形式参数,临时变量
也可以如下理解:
4.传递实参
鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多,可使用位置实参 位置实参 ,这要求实参的顺序与形参的顺序相同;也可使用关键 关键 字实参 字实参 ,其中每个实参都由变量名和值组成;还可使用列表和字典。下面来依次介绍这些方式。
4.1 位置实参
按参数的位置把实参和形参对应起来
def describe_pet(animal_trpe,pet_name): print(" I have a " + animal_trpe+'.') print("My"+animal_trpe+"'s name is " + pet_name.title()+'.') describe_pet('hsmster','harry')
调用函数多次
def describe_pet(animal_trpe,pet_name): print(" I have a " + animal_trpe+'.') print("My"+animal_trpe+"'s name is " + pet_name.title()+'.') describe_pet('hsmster','harry') describe_pet('dog','willie')
位置实参的顺序很重要
4.2 关键字实参
可以不按照顺序,需要指定参数(关键参数要放在位置参数后面)
def describe_pet(animal_trpe,pet_name): print(" I have a " + animal_trpe+'.') print("My"+animal_trpe+"'s name is " + pet_name.title()+'.') describe_pet(animal_trpe='hsmster',pet_name='harry')
4.3 默认值
在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默
def describe_pet(pet_name,animal_trpe='dog'): print(" I have a " + animal_trpe+'.') print("My"+animal_trpe+"'s name is " + pet_name.title()+'.') describe_pet(pet_name='harry')
# 给了形参默认值后,要把他的位置放到最后面,why???
关键字参数必放在位置参数之后
或者animal_trpe已经有了默认值,因此该函数调用中只包含一个实参,就可以写成如下代码
def describe_pet(pet_name,animal_trpe='dog'): print(" I have a " + animal_trpe+'.') print("My"+animal_trpe+"'s name is " + pet_name.title()+'.') describe_pet('harry')
参数的优先级:
位置参数>关键参数默认参数
4.4 等效的函数调用
def describe_pet(pet_name, animal_type='dog'):
基于这种定义,在任何情况下都必须给pet_name 提供实参;指定该实参时可以使用位置方式,也可以使用关键字方式。如果要描述的动物不是小狗,还必须在函数调用中 给animal_type 提供实参;同样,指定该实参时可以使用位置方式,也可以使用关键字方式。
5. 返回值
在函数中,可使用return 语句将值返回到调用函数的代码行
注意:
函数在执行过程中,只要遇到return语句,就会停止执行并返回结果,so,也可以理解为rerurn语句代表着函数结束
如果未在函数中指定return,那这个函数的返回值就是None
5.1 返回简单值
def get_formatted_name(first_name,last_name): full_name=first_name+' '+last_name return full_name.title() a=get_formatted_name('jimi','hendrix') print(a)
>>>Jimi Hendrix
全局变量与局部变量
name="alex" def change_name(name): print("before change:",name) name="金角大王" print("after change",name) change_name(name) print("在外面看看name改了吗?",name)
输出结果
before change: alex after change 金角大王 在外面看看name改了吗? alex
在函数内部无法修改全局变量
locals() 打印函数所有的局部变量
globals() 打印所有的全局变量
局部变量可以引用全局变量
注意:
1.在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量
2.全局变量作用域是整个程序,局部变量作用域是定义该变量的函数
3.当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用,在其他地方全局变量起作用
作用域
一段代码中所用到的名字并不总是有效或者可用的,而限定这个名字的可用性代码范围就是这个名字的作用域
5.2 让实参变成可选的
如果有三个实参,但是这个三个实参并不是全都都会被用到,那么就可以给一个实参默认值,空字符串
def get_formatted_name(first_name,last_name,moddle_name=' '): full_name=first_name+' '+ moddle_name + ' ' +last_name return full_name.title() a=get_formatted_name('jimi','hendrix') print(a)
Jimi Hendrix
5.3 返回字典
def build_person(frist_name,last_name): person={'frist':frist_name,'last':last_name} return person a=build_person('jimi','hendrix') print(a)
def build_person(frist_name,last_name,age=''): person={'frist':frist_name,'last':last_name} if age: person['age']=age return person a=build_person('jimi','hendrix',age=27) print(a)
5.4 结合使用函数和while循环
def get_fomatted_name(frist_name,last_name): full_name=frist_name+' '+ last_name return full_name.title() while True: print(" Pleaae tell me your name:") f_name=input("First name:") l_name=input("Lset name:") fomatted_name = get_fomatted_name(f_name,l_name) print(" Hello ,"+fomatted_name + '.')
以上代码没有定义退出条件,
def get_fomatted_name(frist_name,last_name): full_name = frist_name + ' ' + last_name return full_name.title() while True: print(" Pleaae tell me your name:") print("(enter 'q' at any time to quit)") f_name = input("First name:") if f_name=='q': break l_name = input("Lset name:") if l_name=='q': break fomatted_name = get_fomatted_name(f_name, l_name) print(" Hello ," + fomatted_name + '.')
5.5 传递列表
def greet_users(names): for name in names: msg="hello,"+ name.title()+"!" print(msg) user_names=['hannah','try','margot'] greet_users(user_names)
5.5 在函数中修改列表
def print_models(unprinted_designs,completed_models): while unprinted_designs: current_design=unprinted_designs.pop() print("Print modke:" + current_design) completed_models.append(current_design) def show_completed_models(completed_models): print(" the following models have been printed:") for completed_model in completed_models: print(completed_model) unprinted_designs = ['iphone case ','robot pendant','dodecahedron'] completed_models=[] print_models(unprinted_designs,completed_models) show_completed_models(completed_models)
Print modke:dodecahedron
Print modke:robot pendant
Print modke:iphone case
the following models have been printed:
dodecahedron
robot pendant
iphone case
[]
5.6 禁止函数修改列表
只需将列表的副本传递给函数,可以如下
function_name(list_name[:])
则上述代码可以修改为
def print_models(unprinted_designs,completed_models): while unprinted_designs: current_design=unprinted_designs.pop() print("Print modke:" + current_design) completed_models.append(current_design) def show_completed_models(completed_models): print(" the following models have been printed:") for completed_model in completed_models: print(completed_model) unprinted_designs = ['iphone case ','robot pendant','dodecahedron'] completed_models=[] print_models(unprinted_designs[:],completed_models) show_completed_models(completed_models) print(unprinted_designs)
输出结果:
Print modke:dodecahedron Print modke:robot pendant Print modke:iphone case the following models have been printed: dodecahedron robot pendant iphone case ['iphone case ', 'robot pendant', 'dodecahedron']
5.7 传递任意数量的实参,非固定参数,用(*)
若你的函数在定义是不确定用户想传入多少个参数,就可以使用非固定参数
*args 元祖
**kwargs 字典
def make_pizza(*balala): print(balala) make_pizza('pepper') make_pizza('mushroonms','peppers','cheese')
输出结果
('pepper',) ('mushroonms', 'peppers', 'cheese')
也可以如下:
def stu_reg(name,age,*args):#*args 会把多传入的参数变成一个元祖形式
print(name,age,args) stu_reg('Jack',22,'CN','python')
输出结果:
Jack 22 ('CN', 'python')
还可以有一个**,会把多传入的参数变成一个dict形式
def stu_reg(name,age,*args,**kwargs):#**args 会把多传入的参数变成一个dict形式 print(name,age,args,kwargs) stu_reg('Jack',22,'CN','python',sex='Male',province='shandong')
输入结果
Jack 22 ('CN', 'python') {'sex': 'Male', 'province': 'shandong'}
5.8 将函数存储在模块中
import 语句允许在当前运行的程序文件中使用模块的代码
5.8.1 导入整个模块
用法:
import module_name
module_name.function_name()
先创建一个pizza.py的文件
def make_pizza(size,*toppings): print(" Makeing a "+ str(size)+"-inch pizza with following toppings:") for topping in toppings: print("- "+topping)
然后再创建一个文件makeing_pizzas.py,调用pizza.py
import pizza pizza.make_pizza(16,'pepperoni') pizza.make_pizza(12,'mushroons','green peppers')
执行文件makeing_pizzas.py,执行结果如下:
Makeing a 16-inch pizza with following toppings: - pepperoni Makeing a 12-inch pizza with following toppings: - mushroons - green peppers
5.8.2 导入特定的函数
用法: from module_name import function_name
通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数:
from module_name import function_0, function_1, function_2
对于上个例子,则可以写成如下:
from pizza import make_pizza make_pizza(16,'pepperoni') make_pizza(12,'mushroons','green peppers')
##若使用这种语法,调用函数时就无需使用句点。由于我们在import 语句中显式地导入了函数make_pizza() ,因此调用它时只需指定其名称
5.8.3 使用as给函数指定别名
如果函数名太长,或者与程序现在用的名称冲突,则需要重命名函数,用as
上述代码可以写成如下:
from pizza import make_pizza as mp mp(16,'pepperoni') mp(12,'mushroons','green peppers')
指定别名的通用语法如下:
from module_name import function_name as fn
5.8.4 使用as给模块指定别名
如下:
import pizza as p p.make_pizza(16,'pepperoni') p.make_pizza(12,'mushroons','green peppers')
给模块指定别名的通用语法如下:
import module_name as mn
5.8.5 导入模块中所有的函数
使用*运算符可以让python导入模块中的所有的函数:
from pizza import * make_pizza(16,'pepperoni') make_pizza(12,'mushroons','green peppers')
5.9 函数编写指南
① 给函数指定描述性名称,且只能小写字母和下划线
② 函数应该包含简要地阐述其功能的注释
③ 给形参指定默认值时,等号两边不要有空格
④ 对于函数调用中的关键字实参,也应遵循这种约定
嵌套函数
name='Alex' def chang_name(): name='Alex2' def chang_name2(): name='Alex3' print("第三层打印",name) chang_name2() print('第二层打印:',name) chang_name() print("最外层打印",name)
匿名函数
匿名函数就是不需要显示的指定函数名
lambda
def calc(x,y): return x**y a=calc(2,5) print(a) res=lambda x,y:x**y print(res(2,5))
def math_functype(type): result = 1 if type == 'square': return lambda n:n*n elif type == 'cube': return lambda n:n*n*n else: return lambda n:(1+n)*n/2 math_func = math_functype('cube') print("①",math_func(10)) math_func = math_functype('square') print("②",math_func(10)) math_func = math_functype('other') print("③",math_func(10))
x = map(lambda x:x*x,range(10)) print([e for e in x]) y = map(lambda x:x*x if x %2 ==0 else 0,range(10)) print([e for e in y])
高阶函数
满足一下任意一个条件,就是高阶函数
1. 接受一个或多个函数作为输入
2.return 返回另外一个函数
def add(x,y,f): return f(x)+f(y) res=add(3,-6,abs) print(res)
函数的递归
需要理解????????????
python内置函数
abs
asckii
bin
bool
# 判断一个数据结构是True or False, bool({}) 返回就是False, 因为是空dict
>>> a=[1,2,3] >>> bool(a) True >>> bool([]) False >>> bool({}) False >>> bool(0) False >>>
all
#有空,有0,有none 则false
>>> a=[1,2,None] >>> all(a) False >>> a=[1,2,0] >>> all(a) False >>>
any
#只要有一个True,则True
hytearray
bytes
callable
chr
compile
complex
dict
dir
dirmod
enumerate
eval
exec
exit
filter
float
frozenset
globals
id
isinstance
mpa
max
min
oct
reversed
round
sum
zip
名称空间
存名字x与1绑定关系的地方
不同变量的作用域不同就是由这个变量所在的命名空间决定的
有4中名称空间,且互不干扰
locals:函数内的名称空间,包括局部变量和形参
enclosing:外部嵌套函数的名字空间
globals:全局变量,函数定义所在模块的名字空间
_builtings_:内置模块的名字空间
顺序:
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
闭包现象
可以理解为内层函数调用外层函数的变量,形成闭环,调用外层函数,则会调用内层函数
装饰器
列表生成式:
a = [1,2,3,4,5,6,7,8] b = [i+1 for i in a] print(b)
生成器-通过生成器优化循环的效率
for循环和 while循环的区别:for循环会浪费内存空间,while循环不会
在Python中,这种一边循环一边计算后面元素的机制,称为生成器:generator
g = (i**i for i in range(10)) for i in g: print(i)
函数生成器
斐波那契数列
单线程下的多并发效果,线程就是cpu执行的任务单元
def g_test(): while True: n = yield print("接受到外面传值",n) g = g_test() g.__next__() for i in range(10): g.send(i)
并发
def cuns(name): print("准备吃包子了",name) while True: baozi = yield print("消费者%s接收到的包子编号:%s" %(name,baozi)) c1 = cuns("c1") c2 = cuns("c2") c3 = cuns("c3") c1.__next__() c2.__next__() c3.__next__() for i in range(10): print("--------------成产了第%s批次的包子---------------"%i) c1.send(i) c2.send(i) c3.send(i)
迭代器