函数与函数作用域
功能:
1.减少重复代码
2.方便修改,更易扩展
3.保持代码的一致性
命名规则
- 函数名必须以下划线或字母开头,可以包含任意字母,数字或下划线的组合,不能使用任何的标点符号
- 函数名是区分大小写的
- 函数名不能是保留字
def f():
print('ok')
f() #调用记得加括号
----------------------
def add(a,b): # a,b是形参
print(a+b)
add(8,6) #8,6是实参
编写函数
函数可以通过lambda表达式创建
lambda创建一个对象但将其作为结果返回
- return将一个结果对象发送给调用者
- yield向调用者发回一个结果对象,但是记住他离开的地方
- global声明了一个模块级的变量并被赋值
- nonlocal声明了将要赋值的一个封闭的函数变量
- 函数是通过赋值(对象引用)传递的
- 函数,返回值,变量并不是声明
参数
#参数
def print_info(name,age):
print('name: %s'%name)
print('age: %s'%age)
print_info('xiaohu',38) #关键参数
print_info(age = 39,name ='xiaohu') #关键字参数
#默认参数
def print_info(name,age,sex='mele'): #默认参数必须在其他参数后面
print('name: %s'%name)
print('age: %s'%age)
print('sex: %s'%sex)
print_info('xiaohu',38)
print_info(age = 39,name ='xiaohu',sex='female')
-------------------------------------------------
name: xiaohu
age: 38
sex: mele
name: xiaohu
age: 39
sex: female
#不定长参数1
def add(*args):
sum = 0
for i in args:
sum += i
print(sum)
add(3,4,5,6,7,8,9)
-------------------
42
#不定长参数2
def print_info(*args,**kwargs): #这里*args必须在左边,**kwargs在右边
print(args) #如果有默认参数,放左边
print(kwargs)
# for i in kwargs:
# print('%s:%s'%(i,kwargs[i]))
print_info('wanglei',235,job = 'it',hight = 170)#这里无命名的要和命名的区分开,不能两个数据交叉
-----------------------------------------------
('wanglei', 235)
{'job': 'it', 'hight': 170}
---------------------------
def f(*args):
print(args)
f(*[1,2,3]) #重点
-------------
(1,2,3)
-------------
def f(**kwargs): #传词典
print(kwargs)
# f(name = 'wang',sex = 'mele')
f(**{'name':'wang','sex':'mele'})
-------------
{'name':'wang','sex':'mele'}
优先级:关键字参数>默认参数>*args>**kwargs
def print_info(sex = 'mele',*args,**kwargs):
print(args)
print(kwargs)
print(sex)
# for i in kwargs:
# print('%s:%s'%(i,kwargs[i]))
print_info(235,25555,job = 'it',hight = 170)
--------------------------------------------
(25555,)
{'job': 'it', 'hight': 170}
235 # **235默认赋值给了sex**,后面的按需分配
那这样默认参数的还有什么用,考虑空的情况
return:
函数如果没有return,默认返回None
return多个对象,那么python会帮我们把多个对象封装成一个元组对象
def f():
return 10,'fjf',{0,58},[25,56]
print(f())
函数作用域
四种情况:
L:local,局部作用域,即函数中定义的变量
E:enclosing,嵌套的父级函数的局部作用域,即包含此函数上的局部作用域,但不是全局的
G:globa,全局变量,就是模块级别定义的变量
B:built-in,系统固定模块里面的变量,比如int,bytearray等。搜索变量的优先级顺序依次是:
作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB
局部作用域不能修改全局作用域
count = 10
def outer():
global count #重点,变量声明
print(count)
count = 5
print(count)
outer()
----------------
10
5
def outer():
count = 10
def inner():
nonlocal count
count = 20
print(count)
inner()
print(count)
outer()
-----------
20
20
小结
- 变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域
- 只有模块,类,及函数才能引入新作用域
- 对于一个变量,内部作用域声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量
- 内部作用域要修改外部作用域的值时,全局变量就要使用global关键字,嵌套作用域变量使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个关键字,就能完美的实现闭包了。
- 在不熟悉编程的情况下,最好尽可能的避免使用全局变量(试通过传递函数然后返回值来替代一下),书上说的,你最后会感激自己没用那么多全局变量
高阶函数
def f(n):
return n*n
def foo(a,b,func):
return func(a)+func(b)
foo(3,5,f)
print(foo(3,5,f))
-----------------
34
def foo3():
def inner():
return 8
return inner
ret = foo3()
print(ret())
------------
8
- 函数名可以赋值,因为是一个变量
- 函数名可以作为函数的参数,还可以作为函数的返回值
递归函数
def fat(n):
if n == 1:
return 1 #结束条件
return n*fat(n-1) #自己调用自己
print(fat(5))
--------------
120
- 自己调用自己
- 结束条件
1.但凡是递归都可以用循环写
2.递归的效率在很多时候效率低下,不推荐
菲波那切数列
内置函数
了解内置函数所有python
filter,过滤器
1.循环遍历
2.过滤
str = ['a','b','c','d']
def funl(s):
if s != 'a':
return s
ret = filter(funl,str)
# print(ret)
print(list(ret))
['b', 'c', 'd']
map对序列处理,修改
str = ['a','b','c','d']
def funl(s):
return s + 'wang'
# if s != 'a':
# return s
ret = map(funl,str)
print(ret)
print(list(ret))
-----------------
<map object at 0x0000002CC0BEC5F8> #迭代器地址,map对象,迭代器对象
['awang', 'bwang', 'cwang', 'dwang']
reduce
from functools import reduce
def add1(x,y):
return x*y
print(reduce(add1,range(1,5))) #reduce的结果就是值
lambda匿名函数
add = lambda a,b : a + b
print(add(2,3))
--------------
5
匿名函数的命名规则,用lambda关键字标识,冒号(:)左侧表示函数接收的参数(a,b),冒号(:)右侧表示函数的返回值(a+b)。因为lambda在创建时不需要命名,所以叫匿名函数
相互结合的案例:
#阶乘
from functools import reduce
print(reduce(lambda x,y: x*y,range(1,5)))
--------------------------------------------
24
又比如,map()函数加上lambda表达式(匿名函数)可以实现更强大的功能:
#每个数的平方
squares = map(lambda x : x*x,range(9))
print(squares)
print(list(squares))
-------------------
<map object at 0x000000B0CD58C080>
[0, 1, 4, 9, 16, 25, 36, 49, 64]