Python-函数式编程| “朝闻道”知识分享大赛

小年华°Moon 2024-10-31 11:59:11

这是我参加朝闻道知识分享大赛的第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))

lambda 匿名方法

(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)

函数装饰器decorator

装饰器

(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) 装饰器链:

一个函数可以被多个装饰器修饰,执行顺序为从近到远。

...全文
22 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

1,040

社区成员

发帖
与我相关
我的任务
社区描述
中南民族大学CSDN高校俱乐部聚焦校内IT技术爱好者,通过构建系统化的内容和运营体系,旨在将中南民族大学CSDN社区变成校内最大的技术交流沟通平台。
经验分享 高校 湖北省·武汉市
社区管理员
  • c_university_1575
  • WhiteGlint666
  • wzh_scuec
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

欢迎各位加入中南民族大学&&CSDN高校俱乐部社区(官方QQ群:908527260),成为CSDN高校俱乐部的成员具体步骤(必填),填写如下表单,表单链接如下:
人才储备数据库及线上礼品发放表单邀请人吴钟昊:https://ddz.red/CSDN
CSDN高校俱乐部是给大家提供技术分享交流的平台,会不定期的给大家分享CSDN方面的相关比赛以及活动或实习报名链接,希望大家一起努力加油!共同建设中南民族大学良好的技术知识分享社区。

注意:

1.社区成员不得在社区发布违反社会主义核心价值观的言论。

2.社区成员不得在社区内谈及政治敏感话题。

3.该社区为知识分享的平台,可以相互探讨、交流学习经验,尽量不在社区谈论其他无关话题。

试试用AI创作助手写篇文章吧