Day11 Python课程学习内容

1 高阶函数

  • 含义:接收函数作为参数,或者将函数作为返回的函数就是高阶函数。
  • 高阶函数的优点:可以将一个函数作为参数使用,并将该作为参数函数内的代码传递到目标函数中使用。
# -----------------------------举课堂的一个案例----------------------------- #
'''满足用户获得所有偶数的需求'''
the_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
# 定义一个函数,将制定列表the_lst = [1,2,3,4,5,6,7,8,9,10]中的所有的偶数,保存到一个新的列表中。
def get_even_number(l): # 创建一个get_even_number的函数,用来获取所有的偶数。
	new_list = [] # 创建一个新的列表,用来存储原列表中的所有偶数。
	for number in l: # 创建一个循环,遍历所有列表中的元素。
		if number % 2 == 0: # 创建一个条件,用于判断是否为偶数。
			new_list.append(number) # 将偶数添加到该新列表中。
	return new_list # 将最后的新列表返回。

print(get_even_number(the_lst)) # 调用get_even_number函数,打印包含了所有偶数的列表。

# ----------------------------------分割线----------------------------------

'''满足用户获得所有大于5的数的需求'''
the_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
# 定义一个函数,将制定列表the_lst = [1,2,3,4,5,6,7,8,9,10]中的所有大于5的数,保存到一个新的列表中。
def bigger_number(l): # 创建一个bigger_numbe的函数,用来获取所有的大于5的数。
	new_list = [] # 创建一个新的列表,用来存储原列表中的所有大于5的数。
	for number in l: # 创建一个循环,遍历所有列表中的元素。
		if number > 5: # 创建一个条件,用于判断是否为大于5的数。
			new_list.append(number) # 将大于5的数添加到该新列表中。
	return new_list # 将最后的新列表返回。

print(bigger_number(the_lst)) # 调用bigger_number函数,打印包含了所有大于5的数的列表。

# ----------------------------------分割线----------------------------------

'''为满足用户多样的需求'''
the_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
def for_demand(l):
	def get_even_number(i): # 定义一个判断是否为偶数的函数。
		if i % 2 == 0:
			return True
	new_list = [] # 创建一个新的列表,用来存储原列表中的所有偶数。
	for number in l: # 创建一个循环,遍历所有列表中的元素。
		if get_even_number(number):
			new_list.append(number) # 将偶数添加到该新列表中。
	return new_list # 将最后的新列表返回。

print(for_demand(the_lst)) # 调用for_demand函数,打印包含了所有偶数的列表。
'''
但是并不满足客户任意需求,因为如果客户想要大于5的所有数时,
则需要在函数for_demand中添加新的函数,且要修改if get_even_number(number):这行代码。
如果为获取大于5的所有数的函数名为bigger_number(l),
则需要将if get_even_number(number):改为if bigger_number(number)
即:
'''
the_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
def for_demand(l):
	def get_even_number(i): # 定义一个判断是否为偶数的函数。
		if i % 2 == 0:
			return True
	def bigger_number(i): # 定义一个判断是否为大于5的函数。
		if i > 5:
			return True
	new_list = [] # 创建一个新的列表,用来存储原列表中的所有大于5的数。
	for number in l: # 创建一个循环,遍历所有列表中的元素。
		if bigger_number(number):
			new_list.append(number) # 将大于5的数添加到该新列表中。
	return new_list # 将最后的新列表返回。

print(for_demand(the_lst)) # 调用for_demand函数,打印包含了所有大于5的数的列表。

# ----------------------------------分割线----------------------------------

''' 为满足用户自由选择,使用高阶函数'''
the_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
def get_even_number(i): # 定义一个判断是否为偶数的函数。
	if i % 2 == 0:
		return True
def bigger_number(i): # 定义一个判断是否为大于5的函数。
	if i > 5:
		return True

# 添加一个参数func,需要传递一个函数对象,即此函数对象就为我们想要的新规则,如求所有奇偶数的列表、求所有大于5的列表等等。
def for_demand(func,l): 
	new_list = [] # 创建一个新的列表,用来存储客户需要的数。
	for number in l: # 创建一个循环,遍历所有列表中的元素。
		if func(number):
			new_list.append(number) # 将客户需要的数添加到该新列表中。
	return new_list # 将最后的新列表返回。

print(for_demand(get_even_number,the_lst)) 
# 调用for_demand函数,打印包含了所有偶数的数的列表,get_even_number作为函数的实参,不能遗漏。

print(for_demand(bigger_number,the_lst)) 
# 调用for_demand函数,打印包含了所有大于5的数的列表,bigger_number作为函数的实参,不能遗漏。

在这里插入图片描述

2.匿名函数

  • filter(function, iterable)是一个高阶函数,其作用是可以对一个列表进行过滤。
    function:函数对象; iterable:可迭代对象(序列)。
# -----------------------------举课堂的一个案例-----------------------------
# filter() 高阶函数的使用
lst = [1,2,3,4,5,6,7,8,9,10]
def get_odd_number(i):# 求所有奇数
	if i % 2 != 0:
		return True
	return False
# filter() 返回值为一个filter对象
print(filter(get_odd_number,lst)) # <filter object at 0x0000000002F720F0>

在这里插入图片描述

# -----------------------------举课堂的一个案例-----------------------------
# filter() 高阶函数的使用
lst = [1,2,3,4,5,6,7,8,9,10]
def get_odd_number(i):# 求所有奇数
	if i % 2 != 0:
		return True
	return False
# filter() 返回值为一个filter对象
print(list(filter(get_odd_number,lst))) # 如果想得到我们想要的值,则在filter前加上list。

在这里插入图片描述


综上可见:我们目的是为了得到所有奇数,却使用filter()函数,大大浪费了计算机内存。接下来介绍匿名函数。


  • 匿名函数 lambda(语法糖) 可以用创建一些简单的函数,是函数的另外一种创建方式。
'''
语法
lambda 参数列表 : 返回值
'''
# -----------------------------举课堂的一个案例-----------------------------
# 不使用filter()高阶函数,使用lambda匿名函数,来获取列表中的所有奇数。
'''lambda 第一种使用方式'''
get_add_number = lambda a,b : a + b
print(get_add_number(100,200))

'''注意'''
# 在不传递参数的情况下,传递的是lambda对象,所以要传递参数。
print(get_add_number) 
# <function <lambda> at 0x00000000031E5400>

# --------------------------------分割线--------------------------------

'''lambda 第二种使用方式'''
print((lambda a,b : a + b)(100,200))
# 在不传递参数的情况下,传递的是lambda对象,所以要传递参数。
'''注意'''
print(lambda a,b : a + b) 
# <function <lambda> at 0x00000000031E5400>

lambda的优点:
1.在程序中只会调用一次,调用之后从内存中消失。
2.使用简单、方便。
lambda的限制:
1.不能写复杂的语句,如for循环、遍历等等。


3 闭包

  • 含义:将函数作为返回值返回的函数就是高阶函数
# -----------------------------举课堂的一个案例-----------------------------

def fn_1(): # fn_1 为高阶函数。
	def fn_2(): # 函数内部创建一个函数fn_2。
		print('Hallo Python')
	return fn_2	# 返回一个函数对象。

print(fn_1()) # 打印fn_1的返回值fn_2函数对象。但不但会fn_2函数内代码。
# <function fn_1.<locals>.fn_2 at 0x0000000002FC5400>

# ---------------------------------分割线----------------------------------

'''如果想返回fn_2内的代码。'''
def fn_1(): # fn_1 为高阶函数。
	def fn_2(): # 函数内部创建一个函数fn_2。
		print('Hallo Python')
	return fn_2	# 返回一个函数对象。

r = fn_1() 
r() # 由于没有返回值直接r()

在这里插入图片描述


闭包作用:通过闭包可以创建一些只有当前函数能够访问的变量,可以将一些重要或不希望别人看见的函数隐藏在函数中。


# -----------------------------举课堂的一个案例-----------------------------
# 列表内所有数的平均数。
lst = [30,50,10,20,80]
# sum()求列表中元素之和。
print(sum(lst)/len(lst))
# 结果为 38

# ---------------------------------分割线----------------------------------
# 定义一个函数来求多个数的平均数。
lst = [] # 创建一个空列表
def average(n):	# n 为添加到列表中的数
	lst.append(n)
	return sum(lst)/len(lst)
print(average(10), lst) # lst = [10] 10 / 1 = 10
print(average(10), lst) # lst = [10, 10] 20 / 2 = 10

lst = [] # 当有特殊情况,不小心添加了lst = [],会将前面已经添加了元素的列表lst,重新变成了空值。
# 重新开始计算。
print(average(10), lst) # lst = [10] 10 / 1 = 10

# 或者添加了 lst.append('python')
print(average(10), lst) # 就会报错!!!

在这里插入图片描述
在这里插入图片描述


为了解决以上问题,使用闭包原理。


# -----------------------------------课堂解决方案-----------------------------------
def make_fn():# 创建一个外函数
	lst = [] # 将空列表存储在make_fn函数中,不受make_fn函数外的与句影响。
	def average(n):	# n 为添加到列表中的数 average 函数就是闭包。
		lst.append(n)
		return sum(lst)/len(lst)
	return average
fn = make_fn()
print(fn(10)) # lst = [10] 10 / 1 = 10
print(fn(10)) # lst = [10, 10] 20 / 2 = 10
lst = [] # 不影响make_fn函数内的lst列表。
print(fn(10)) # lst = [10, 10, 10] 30 / 1 = 10

在这里插入图片描述


总结:形成闭包的条件
1 函数需要嵌套。
make_fn 函数内还有一个 average 函数。

2 将内部函数作为返回值返回。
内部函数average 返回值为 sum(lst)/len(lst)

3 内部函数必须要使用到外部函数的变量。
外部函数变量 lst = [ ] 的值在不停增加。


4 装饰器

# -----------------------------------课堂案例-----------------------------------
# 创建简单的几个函数
def add(number1, number2): # 创建两个数相加的函数。
	return number1 + number2 # 求任意两个数的和。

def mul(number1, number2): # 创建两个数相乘的函数。
	return number1 * number2 # 求任意两个数的积。

number_add = add(1, 2)
print(number_add) # 3
number_mul = add(2, 4)
print(number_mul) # 8
# -----------------------------------分割线-----------------------------------
# 案例修改语句...
'''
目前为止直接修改函数代码来满足需求,但会遇到问题:
如果函数太多,修改麻烦。
后期维护麻烦。
违反开闭原则(ocp) 要求对开发程序的扩展,但要求关闭对程序修改。
'''

def add(number1, number2): # 创建两个数相加的函数。
	print('开始工作...')
	result = number1 + number2 # 求任意两个数的和。
	print('结束工作...')
	return  result 

def mul(number1, number2): # 创建两个数相乘的函数。
	return number1 * number2 # 求任意两个数的积。

number_add = add(1, 2)
print(number_add)
'''
开始工作...
结束工作...
3
'''

# -----------------------------------分割线-----------------------------------

# 再不修该函数的情况下,扩展函数
def add(number1, number2): # 创建两个数相加的函数。
	return number1 + number2 # 求任意两个数的和。

def new_add(number1, number2): # 不违反ocp原则,再创建一个新的函数。
	print('开始工作...')
	result = add(number1, number2)
	print('结束工作...')
	return result
result = new_add(1,2)
print(result)
'''
开始工作...
结束工作...
3
'''
'''如果还要添加mul,则需要重新添加 new_mul函数,十分麻烦'''
# -----------------------------------分割线-----------------------------------

'''引入装饰器'''
def start_end():
	# 用来对其他的函数进行扩展,扩展功能,添加两个打印语句。
	
	# 创建一个函数
	def new_function():
		pass
	# 返回新的函数
	return new_function
result = start_end()
print(result) # <function start_end at 0x00000000031D6378>

# -----------------------------------分割线-----------------------------------

def other_function():
	print('Hello World')

def start_end(old): # 参数old 用来扩展参数
	def new_function():
		print('Start.......')
		old()
		print('End.......')
	return new_function
result = start_end(other_function)
result()

'''
Start.......
Hello World
End.......
'''
# -----------------------------------分割线-----------------------------------
# 再添加一个函数。
def add(number1, number2): # 创建两个数相加的函数。
	return number1 + number2 # 求任意两个数的和

def start_end(old): # 参数old 用来扩展参数
	def new_function(number1, number2):
		print('Start.......')
		result = old(number1, number2)
		print('End.......')
		return result 
	return new_function
result_1 = start_end(add)
result_2 = result_1(1,2)
print(result_2)
'''
Start.......
End.......
3
'''
'''发现依旧很麻烦,需要修改start_end函数内的代码'''
# -----------------------------------分割线-----------------------------------
def other_function():
	print('Hello World')
	
def add(number1, number2): # 创建两个数相加的函数。
	return number1 + number2 # 求任意两个数的和

def start_end(old): # 参数old 用来扩展参数
	def new_function(*number1, **number2):
		print('Start.......')
		result = old(*number1, **number2)
		print('End.......')
		return result 
	return new_function
result = start_end(other_function)
result()

result_1 = start_end(add)
result_2 = result_1(1,2)
print(result_2)

在这里插入图片描述


类似start_end(old) 这一类函数我们称之为装饰器。
通过装饰器,可以在不修改原函数的情况下,对其他函数进行扩展。
在开发中,都是运用装饰器来对函数进行扩展的。
程序员千万不要去修改同事的代码


def start_end(old): # 参数old 用来扩展参数
	def new_function(*number1, **number2):
		print('Start.......')
		result = old(*number1, **number2)
		print('End.......')
		return result 
	return new_function

@start_end # 使用@符号来扩展
def speak():
	print('figting')

speak()

在这里插入图片描述

5 命名空间

  • 使用 locals() 来获取当前作用域的命名空间,且返回一个 字典
# -----------------------------------课堂案例-----------------------------------
a = 10
def f():
	print('Hello Python')

scope = locals()
print(scope)

在这里插入图片描述

# 在locals()返回的字典内查询不存在的key-value。
a = 10
def f():
	print('Hello Python')
scope = locals()
scope['c'] = 123 # 向命名空间内添加了一个key-value,等于在全局中创建一个变量
print(c)
print(scope)

在这里插入图片描述

# 在函数内使用locals()。
a = 10
def f():
	print('Hello Python')
	scope = locals()
	scope['c'] = 123 
	print(scope)
f()

在这里插入图片描述


不要使用locals()在当前域中添加值。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值