函数作用域
1.作用域即范围
- 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
- 局部范围(局部名称空间属于该范围):临时存活,局部有效
2.作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关
3.查看作用域,LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
- locals 是函数内的名字空间,包括局部变量和形参
- enclosing 外部嵌套函数的名字空间(闭包中常见)
- globals 全局变量,函数定义所在模块的名字空间
- builtins 内置模块的名字空间
一、匿名函数
匿名函数关键字 形参:(处理逻辑)返回值
lambda argument_list: expression
调用方法(不应该这么使用):
func = lambda x:x+1
func(x)
在需要返回多个值的时候,需要自己加上括号变成元组,因为函数中的return会自动把返回值变成元组形式
一般情况下,不适用Lambda函数,而是将其与高阶函数一起使用(如python内置的高阶函数Map, Reduce等)。
假设有一个整数列表,必须返回三个输出。
- 一个列表中所有偶数的和
- 一个列表中所有奇数的和
- 一个所有能被三整除的数的和
首先假设用普通函数来处理这个问题。在这种情况下,将声明三个不同的变量来存储各个任务,并使用一个for循环处理并返回结果三个变量。该方法常规可正常运行。
现在使用Lambda函数来解决这个问题,那么可以用三个不同的Lambda函数来检查一个待检验数是否是偶数,奇数,还是能被三整除,然后在结果中加上一个数。
def return_sum(func, lst):
result = 0
for i in lst:
#if val satisfies func
if func(i):
result = result + i
return result
lst = [11,14,21,56,78,45,29,28]
x = lambda a: a%2 == 0
y = lambda a: a%2 != 0
z = lambda a: a%3 == 0
print(return_sum(x, lst))
print(return_sum(y, lst))
print(return_sum(z, lst))
# 输出
176
106
144
二、函数式编程
编程的方法论:
- 面向过程:找到解决问题的入口,按照一个固定的流程去模拟解决问题的流程
- 函数式:用编程语言去实现数学函数,所有循环都由递归去实现,无变量的赋值
- 面向对象
函数式编程
高阶函数
- 把函数当作参数传给另一个函数(也可以把自己作为返回值)
- 返回值中包含函数
def test():
print('Test 1')
return test()
def example():
print('Example 1')
return example
# t = test() # 死循环,不断执行test
e = example() # 返回函数地址
e()
# 输出
Example 1
Example 1
尾调用(尾递归优化):在函数执行的最后一步执行另一个函数
在A函数调用时会将A函数放入调用栈中,如果在A函数中存在另一个函数B调用,此时也会将B压入调用栈中,等待函数B调用完成后,此时才可以从调用栈中弹出函数A和函数B。那如果使用尾调用时,当执行函数A时,将函数A压入调用栈中,当执行A时发现存在函数B,并且函数B为函数A的最后一步调用,此时可以将函数A从调用栈中弹出,将函数B压入调用栈中。这样下来性能就做到了优化。
尾递归:如果尾调用自身则称为尾递归。
递归非常消耗内存,因为需要同时保存成千上万个调用记录,很容易发生栈溢出的错误。但是对于尾递归来说,由于只存在一个调用记录,所以永远不会发生栈溢出。同时可以对函数中的某些参数使用默认值,这样当我们没有输入该参数时,就会使用默认值
map函数:map(处理方法,可迭代对象)
处理方法可以是lambda匿名函数也可以是定义函数
处理序列中的每个元素,得到一个‘列表’,该‘列表’元素个数及位置与原来一样
【迭代可迭代对象中的每个元素进行相应的转换操作】
before = [1,2,3]
after = list(map(lambda x:x*2, before))
# after is [2,4,6]
filter函数:filter(处理方法,可迭代对象)
处理方法可以是lambda匿名函数也可以是定义函数
遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来
【用于可迭代,仅保留满足特定条件的某些元素】
before = [1,2,3,4,5,6]
after = list(filter(lambda x:x%2==1, before))
# after is [1,3,5]
reduce函数:reduce(处理方法,可迭代对象,init)
处理方法可以是lambda匿名函数也可以是定义函数
【lambda函数需要两个参数,用于将两个元素组合起来】
处理一个序列,然后把序列进行合并操作
【以某种方式在组合可迭代对象中的所有元素】
from functools import reduce #现在必须从模块中引入reduce
before = [1,2,3,4,5]
after = reduce(lambda a,b: a*b, before)
# after is 120
三、常见内置函数
内置函数 | 功能 |
---|---|
abs() | 返回绝对值 |
all() | 如果可迭代对象中每个元素都为True则返回True |
any() | 如果可迭代对象中有任何一个元素为True则返回True |
bin() | 将整数转换为二进制数 |
hex() | 将整数转换为十六进制数 |
oct() | 将整数转换为八进制数 |
bool() | 判断对象是否为真 |
bytes() | 将对象转换为二进制格式 |
chr() | 将ASCII码转换为字符 |
ord() | 将字符转换为ASCII码 |
dir() | 打印对象中存在的方法和属性 |
divmod() | 返回整除和取模的结果 |
eval() | 执行字符串中的表达式并返回结果 |
hash() | 对对象进行哈希运算 |
isinstance() | 判断对象是否为指定类的实例 |
globals() | 返回全局变量的字典 |
locals() | 返回局部作用域的字典 |
max() | 返回可迭代对象中的最大值 |
min() | 返回可迭代对象中的最小值 |
max()和min()方法
1.处理得是可迭代对象,相当于一个for循环取出每个元素进行比较,但不同类型之间不可以相互比较;
2.每个元素间进行比较,是从每个元素的第一个位置依次比较,如果这一个位置分出大小,后面就不需要比较了,直接得出两个元素大小
dic = {'age1':18, 'age2':20, 'age3':152}
print(list(max(zip(dic.values(), dic.keys()))))
# 输出
[152, 'age3']
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。