1,040
社区成员




这是我参加朝闻道知识分享大赛的第34篇文章。
(1) 定义:用一系列函数解决问题。
-- 函数可以赋值给变量,赋值后变量绑定函数。
-- 允许将函数作为参数传入另一个函数。
-- 允许函数返回一个函数。
(2) 高阶函数:将函数作为参数或返回值的函数。
2048 游戏核心算法(11.23)
谈架构(类间)低耦合
显示(界面)与控制(算法)分离
控制台
PyQt
PyGame
谈算法
1. (类内)高内聚: (类间)低耦合
上下移动 -矩阵转置-> 左右移动
向左移动 --> 合并数据 --> 零元素后移
向右移动 -翻转-> 合并数据 --> 零元素后移
2. 降维思想:
将二维列表的操作,改为对一维列表的操作.
将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则。
def func01():
print("func01")
func01() # 直接调用
# a = func01() # 调用函数,将返回值赋值给变量
a = func01
a() # 间接调用
def func02():
print("func02")
def func03(func):
print("func03")
# func02() # 直接调用:固定的,不灵活的
# 确定使用方法(参数与返回值)
func() # 间接调用:由实参决定搭配关系
func03(func02)
def func04(p):
print("参数是:",p)
func03(func04)
"""
函数式编程思想:
适用性:
多个函数,主体逻辑相同,但核心算法不同.
步骤:
1."封装"[分]:根据需求将多个变化点分别定义到函数中
2."继承"[隔]:将变化的函数抽象为参数
在通用函数中先确定参数的使用方式
隔离了通用函数与变化函数
3."多态"[做]:按照通用函数中确定的使用方式,创建变化函数.
"""
list01 = [43, 54, 65, 76, 8, 9]
"""
# 需求:查找第一个小于10的数字
def find_single_lt_10():
for item in list01:
if item < 10:
return item
# 需求:查找第一个大于20的数字
def find_single_gt_20():
for item in list01:
if item > 20:
return item
"""
# 变化
def condition01(item):
return item < 10
def condition02(item):
return item > 20
# 不变(通用函数)
def find_single(condition):
for item in list01:
# if item < 10:
# if condition01( item ):
# if condition02( item ):
# 统一使用方法
if condition(item):
return item
# 新增查找奇数的需求
def condition_new(item):
return item % 2 != 0
print(find_single(condition_new))
print(find_single(condition01))
print(find_single(condition02))
(1) 定义:是一种匿名方法
(2) 作用:
-- 作为参数传递时语法简洁,优雅,代码可读性强。
-- 随时创建和销毁,减少程序耦合度。
-- lambda能完成的功能,def都可以完成
(3) 语法
# 定义:
变量 = lambda 形参 : 方法体(只能是一条语句且不能是赋值语句)
# 调用:
变量(实参)
# 1. 有参数有返回值
def func01(p1, p2):
return p1 > p2
func01 = lambda p1, p2: p1 > p2
# 2. 有参数无返回值
def func02(p1):
print("参数是:",p1)
func02 = lambda p1: print("参数是:", p1)
# 3. 无参数有返回值
def func03():
return 100
func03 = lambda: 100
# 4. 无参数无返回值
def func04():
print("func04")
func04 = lambda: print("func04")
# 注意1:lambda函数体只能有一条语句
def func05():
for i in range(5):
print(i)
# func05 = lambda :for i in range(5):print(i)(这个就不行)
# 注意2:lambda不支持赋值语句
def func06(p):
p[0] = 100
list01 = [10]
func06(list01)
print(list01) # [100]
# func06 = lambda p: p[0] = 100(这个就不行)
(4) 说明:
-- 形参没有可以不填
-- 方法体只能有一条语句,且不支持赋值语句。
(5) 应用:
from common.iterable_tools import IterableHelper
# 定义函数,在列表中查找所有大于100的数
# def condition01(number):
# return number > 100
# 定义函数,在列表中查找所有偶数
# def condition02(number):
# return number % 2 == 0
list01 = [342, 4, 54, 56, 6776]
# 用了lambda,可以让函数作为参数写在一行
for item in IterableHelper.find_all(list01,lambda number: number > 100):
print(item)
for item in IterableHelper.find_all(list01,lambda number: number % 2 == 0):
print(item)
(1) map(函数,可迭代对象):用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
(2) filter(函数,可迭代对象):根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
(3) sorted(可迭代对象,key = 函数,reverse = True(反转为降序排列)):排序,返回值为排序结果。
(4) max(可迭代对象,key = 函数):根据函数获取可迭代对象的最大值。
(5) min(可迭代对象,key = 函数):根据函数获取可迭代对象的最小值。
(6) 演示:
class Employee:
def __init__(self, eid, did, name, money):
self.eid = eid # 员工编号
self.did = did # 部门编号
self.name = name
self.money = money
# 员工列表
list_employees = [
Employee(1001, 9002, "师父", 60000),
Employee(1002, 9001, "孙悟空", 50000),
Employee(1003, 9002, "猪八戒", 20000),
Employee(1004, 9001, "沙僧", 30000),
Employee(1005, 9001, "小白龙", 15000),
]
# 1. map 映射
# 需求:获取所有员工姓名
for item in map(lambda item: item.name, list_employees):
print(item)
# 2. filter 过滤器
# 需求:查找所有部门是9002的员工
for item in filter(lambda item: item.did == 9002, list_employees):
print(item.__dict__)
# 3. max min 最值
emp = max(list_employees, key=lambda emp: emp.money)
print(emp.__dict__)
# 4. sorted
# 升序排列
new_list = sorted(list_employees, key=lambda emp: emp.money)
print(new_list)
# 降序排列
new_list = sorted(list_employees, key=lambda emp: emp.money, reverse=True)
print(new_list)
逻辑连续,当内部函数被调用时,不脱离当前的逻辑。
(1) 三大要素:
-- 有外有内:必须有一个内嵌函数。
-- 内使用外:内嵌函数必须引用外部函数中变量。
-- 外返回内:外部函数返回值必须是内嵌函数。
(2) 语法
# 定义:
def 外部函数名(参数):
外部变量
def 内部函数名(参数):
使用外部变量
return 内部函数名
# 调用:
变量 = 外部函数名(参数)
变量(参数)
(3) 定义:是由函数及其相关的引用环境组合而成的实体。
(4) 优点:内部函数可以使用外部变量。
(5) 缺点:外部变量一直存在于内存中,不会在调用结束后释放,占用内存。
(6) 作用:外部函数调用后,栈帧保留,供内部函数不断使用。实现python装饰器。
(7) 演示:
def func01():
a = 10
def func02():
print(a)
return func02
# 调用外函数,接收内函数
result = func01()
# 调用内函数
result()
"""
闭包-应用
逻辑连续
从得2000元钱,到不断购买商品的过程连续不中断.
"""
def get_new_year_money(money):
print(f"获得了{money}元压岁钱")
def child_buy(commodity, price):
nonlocal money
money -= price
print(f"孩子花了{price}元购买了{commodity},还剩下{money}")
return child_buy
action = get_new_year_money(2000)
action("游戏机", 500)
action("电脑", 1000)
action("手机", 300)
(1) 定义:在不改变原函数的调用以及内部代码情况下,为其添加新功能的函数。
(2) 语法
def 函数装饰器名称(func):
def wrapper(*args, **kwargs):
需要添加的新功能
res = func(*args, **kwargs)
return res
return wrapper
@ 函数装饰器名称
def 原函数名称(参数):
函数体
原函数(参数)
(3) 本质:使用“@函数装饰器名称”修饰原函数,等同于创建与原函数名称相同的变量,关联内嵌函数;故调用原函数时执行内嵌函数。
原函数名称 = 函数装饰器名称(原函数名称)
"""
装饰器 - 推导过程
在不改变旧功能调用与定义的情况下,
为其增加新功能
闭包三大要素在装饰器中的作用:
有外有内:外在接收旧功能,内函数包装新旧功能
内访问外:希望同时执行新旧功能
外返回内:日后根据需求执行新旧功能
"""
# 不改变旧功能,实现性功能
def func01():
print("旧功能")
def func_new(func):
def wrapper():
print("新功能")
func()
return wrapper # 返回内函数,不能加()
# 调用外函数(不执行内函数)
func01 = func_new(func01)
# 调用内函数(执行了新和旧的功能)
func01()
"""
装饰器 - 标准
内函数的返回值:旧功能的返回值
"""
def func_new(func):
def wrapper(*args):# 2 合
print("新功能")
res = func(*args) # 调用旧功能 拆
return res
return wrapper
# func01 = func_new(func01)
@func_new
def func01(p1):# 3
print("旧功能1")
return 100
@func_new
def func02(p1,p2):# 3
print("旧功能2")
# func01 = func_new(func01)
# func02 = func_new(func02)
# 1
value = func01(10) # 调用内函数
value = func02(10,20) # 调用内函数
print(value)
"""
练习:
为sum_data,增加打印函数执行时间的功能.
函数执行时间公式: 执行后时间 - 执行前时间
"""
import time
def print_execution_time(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 旧功能
stop = time.time()
print("函数执行时间:", stop - start)
return res
return wrapper
@print_execution_time # 调用外函数,
def sum_data(n):
sum_value = 0
for number in range(n):
sum_value += number
return sum_value
print(sum_data(10)) # 调用内函数
(3) 装饰器链:
一个函数可以被多个装饰器修饰,执行顺序为从近到远。