Python学习之函数(二)
1.函数(变量)作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:
- L (Local) 局部作用域
- E (Enclosing) 闭包函数外的函数中
- G (Global) 全局作用域
- B (Built-in) 内建作用域
以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
x = int(2.9) # 内建作用域
test1 = 0 # 全局作用域
def outer():
test2 = 1 # 闭包函数外的函数中
def inner():
test3 = 2 # 局部作用域
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:
>>> if True: ... msg = 'I am from Run' ... >>> msg 'I am from Run' >>>
实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。
如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:
>>> def test(): ... msg_inner = 'I am from Runoob' ... >>> msg_inner Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'msg_inner' is not defined >>>
从报错的信息上看,说明了 msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。
2.匿名函数
python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
1.普通函数:
def calc(x):
return x+1
res=calc(10)
print(res) ==》 11
print(calc) ==》 <function calc at 0x00000015026A3E18>
2.匿名函数:
print(lambda x:x+1) ==》 # <function <lambda> at 0x0000008CC1233E18>
func=lambda x:x+1
print(func(10)) ==》 11
3. 函数式编程
编程的方法论:面向对象;函数式; 面向对象
函数式编程特性:
不可变数据 ;第一类对象; 尾调用优化(尾递归)
# 把函数当做参数传给另外一个函数
def foo(n): #n=bar
print(n)
def bar(name):
print('my name is %s' %name)
foo(bar) # 返回bar的地址<function bar at 0x000000DDDE7D4158>
foo(bar()) #缺少参数报错
foo(bar('alex')) ==>my name is alex
None {注:foo(bar)没有return所以返回None}
4.高阶函数:1.函数接收的参数是一个函数名 2.返回值中包含函数
5.尾调用:在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)
6.map函数
array=[1,3,4,71,2]
ret=[]
for i in array:
ret.append(i**2)
print(ret) ==》[1, 9, 16, 5041, 4]
#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数
def map_test(array):
ret=[]
for i in array:
ret.append(i**2)
return ret
print(map_test(array)) ==》[1, 9, 16, 5041, 4]
#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样
def add_num(x):
return x+1
def map_test(func,array):
ret=[]
for i in array:
ret.append(func(i))
return ret
print(map_test(add_num,array)) ==》[2, 4, 5, 72, 3]
#可以使用匿名函数
print(map_test(lambda x:x-1,array)) ==》[0, 2, 3, 70, 1]
#上面就是map函数的功能,map得到的结果是可迭代对象
print(map(lambda x:x-1,range(5))) ==》<map object at 0x0000000001D75550>
num_l=[1,2,10,5,3,7]
def map_test(func,array): #func=lambda x:x+1 arrary=[1,2,10,5,3,7]
ret=[]
for i in array:
res=func(i) #add_one(i)
ret.append(res)
return ret
print(map_test(lambda x:x+1,num_l)) ==》[2, 3, 11, 6, 4, 8]
res=map(lambda x:x+1,num_l)
print('内置函数map,处理结果',res) ==》内置函数map,处理结果 <map object at 0x0000000002730CC0>
#注:map(--,--) 第二个参数不一定必须是列表,可迭代即可,函数精简时第一个参数用匿名函数格式比较好
msg='rongxj'
print(list(map(lambda x:x.upper(),msg))) ==》['R', 'O', 'N', 'G', 'X', 'J'] #函数式编程通常只用一行代码书写简单但易读性差
7.filter函数
#电影院聚集了一群看电影bb的傻逼,让我们找出他们
movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']
def tell_sb(x):
return x.startswith('sb')
def filter_test(func,array):
ret=[]
for i in array:
if func(i):
ret.append(i)
return ret
print(filter_test(tell_sb,movie_people)) ==》['sb_alex', 'sb_wupeiqi', 'sb_yuanhao']
#函数filter,返回可迭代对象
print(filter(lambda x:x.startswith('sb'),movie_people)) ==》<filter object at 0x00000000021EE160>
res=filter(lambda x:not x.startswith('sb'),movie_people)
print(list(res)) ==》['alex', 'wupeiqi', 'yuanhao']
res=filter(lambda x: x.startswith('sb'),movie_people)
print(list(res)) ==》['sb_alex', 'sb_wupeiqi', 'sb_yuanhao']
8.reduce函数
列表数相加:
num_l=[1,2,3,100]
res=0
for num in num_l:
res+=num
print(res) ==》106
列表数相加(函数方式):
num_l=[1,2,3,100]
def reduce_test(array):
res=0
for num in array:
res+=num
return res
print(reduce_test(num_l)) ==》106
#列表数相乘:
num_l=[1,2,3,100]
def reduce_test(func,array):
res=array.pop(0)
for num in array:
res=func(res,num)
return res
print(reduce_test(lambda x,y:x*y,num_l)) ==》600
#在100的基础上乘以列表的值:
num_l=[1,2,3,100]
def reduce_test(func,array,init=None):
if init is None:
res=array.pop(0)
else:
res=init
for num in array:
res=func(res,num)
return res
print(reduce_test(lambda x,y:x*y,num_l,100)) ==》60000
#reduce函数
from functools import reduce #需导入此模块
num_l=[1,2,3,100]
print(reduce(lambda x,y:x+y,num_l,1)) ==》107
print(reduce(lambda x,y:x+y,num_l)) ==》106
小结三种函数:
map原有基础上加工数据,处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样
filter筛选列表值,遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下
reduce合并数据,得到最终结果;处理一个序列,然后把序列进行合并操作
#reduce用来计算1到100的和 from functools import reduce print(reduce(lambda x,y:x+y,range(100),100)) ==》5050 #后面的100是给一个初始值 print(reduce(lambda x,y:x+y,range(1,101))) ==》5050

浙公网安备 33010602011771号