深入浅出一下Python函数的核心概念与进阶应用

本篇技术博文摘要 🌟

  • 本文系统梳理了Python函数的核心知识点,从基础概念到高级特性,构建了完整的函数编程知识体系。内容涵盖:变量作用域 的局部与全局划分、函数注释 的规范写法、参数传递中值与引用 的区别、匿名函数 的灵活应用,以及Python 3.8的新特性 (如海象运算符)。进一步深入偏函数嵌套函数闭包 的实现,详解装饰器 的语法与进阶用法(参数传递、多装饰器顺序、返回值处理)。最后结合高阶函数(mapfilterreduce)实现数据批量操作,并通过综合实验------工资计算系统,串联知识点,实践员工信息管理与月薪计算逻辑。

引言 📘

  • 在这个变幻莫测、快速发展的技术时代,与时俱进是每个IT工程师的必修课。
  • 我是盛透侧视攻城狮,一名什么都会一丢丢的网络安全工程师,也是众多技术社区的活跃成员以及多家大厂官方认可人员,希望能够与各位在此共同成长。

上节回顾

目录

[本篇技术博文摘要 🌟](#本篇技术博文摘要 🌟)

[引言 📘](#引言 📘)

上节回顾

01-函数中变量的作用域

02-函数注释

03-值传递引用传递

04-Py函数以及匿名函数

05-python3.8新特性

06-偏函数

​07-函数的嵌套

08-闭包

09-装饰器

10-装饰器参数

11-一个函数被多个装饰器装饰

12-装饰器函数返回值问题

13-高阶函数map.py

14-filter函数

15-reduce函数

综合实验:设计一个工资计算系统,录入员工信息,计算员工的月薪

欢迎各位彦祖与热巴畅游本人专栏与技术博客

你的三连是我最大的动力

点击➡️指向的专栏名即可闪现


01-函数中变量的作用域

  • 原理:Python变量作用域分为局部作用域(函数内部)和全局作用域(函数外部)。
  • 作用:理解变量可见性和生命周期
python 复制代码
a = 100


def test_01():
    a = 10
    b = 20
    print(a)
    print(b)


def test_02():
    print(a)


def test_03():
   
    global a
    a += 100
    print(a)


test_03()
# test_02()
# test_01()
# print(b)

'''
全局变量:声明在函数外部的变量称为全局变量

'''
  • 函数内部可以使用全局变量,但是不能修改,如果一定要在函数内部修改全局变量,那么global

02-函数注释

  • 原理 :使用文档字符串("""...""")和类型注解(Python 3.5+)为函数添加说明。
  • 作用:提高代码可读性,IDE可识别提示
python 复制代码
def add(a: int, b: int) -> int:
    """返回两个整数的和"""
    return a + b
print(add.__doc__)  # 输出:返回两个整数的和

03-值传递引用传递

  • 原理
    • 值传递:在传递参数的时候,仅仅是将自己的值拷贝了一份,传递给了函数的参数,变量不会改变
    • 引用传递:在传递参数时,传地址,函数形参获取的值也是同一块内存
  • 作用:理解参数修改对原数据的影响
python 复制代码
def test_01(x, y):
    x += 10
    y += 100
    print(x)
    print(y)


a = 10
b = 20
test_01(a, b)
print(a)
print(b)



def test_02(nums):
    print(id(nums))
    nums.append(10)
    nums.append(100)
    print(nums)


list1 = [1, 2, 3]
print(id(list1))
test_02(list1)
print(list1)

04-Py函数以及匿名函数

  • 原理
    *

    python 复制代码
    lambda [arg1,arg2......]: 代码块(函数体)
    • 存在函数作为参数传递给函数,并且又不想让外界访问,而且参数函数足够简单,即可以定义为匿名函数(lambda表达式)
  • 作用:简化代码,常用于高阶函数参数

python 复制代码
def now():
    print("1111111111")

f = now
a = f
# __name__,拿到函数的名字
print(f.__name__)
print(a.__name__)
python 复制代码
def test_func(add):
     result = add(1, 2)
     print(result)



def compute(a,b):
     return a+b


test_func(compute)


test_func(lambda a, b: a + b)
  • function(){}
  • 在python中,将一个函数作为参数传到另一个函数中去
  • 函数的参数数据类型:只要是一个对象就可以
  • 函数本身就是一个对象

05-python3.8新特性

  • 原理 :Python 3.8引入海象运算符(:=)、位置参数限定符(/)等。
  • 作用:提升代码简洁性和灵活性
python 复制代码
# 海象运算符
if (n := len([1,2,3])) > 2:
    print(f"长度是{n}")  # 输出:长度是3

# 位置参数
def func(a, b, /, c):
    print(a, b, c)
func(1, 2, c=3)  # 正确
func(a=1, b=2, c=3)  # 报错:a,b必须位置参数
python 复制代码
# 声明函数参数类型
# def 函数名(a,b)

def add(x: int, y: int) -> int:
    return x + y


print(add(1, 2))
print(add("a", "b"))

06-偏函数

  • 原理 :使用 functools.partial 固定函数的部分参数,生成新函数。
  • 作用:简化参数传递。
python 复制代码
from functools import partial
def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
print(square(5))  # 输出25
python 复制代码
# functools模块提供很多方法,其中有一个就是偏函数

# int(3.14)

# def int2(x, base=2):
#     return int(x, base)
#
# print(int2("10010",10))

import functools

int2 = functools.partial(int, base=2)

print(int2("100101"))

07-函数的嵌套

  • 原理:在函数内部定义另一个函数。
  • 作用:封装逻辑,限制函数作用域。
python 复制代码
def outer():
    def inner():
        print("内部函数")
    inner()

outer()  # 输出:内部函数
python 复制代码
def fun1():
    b = 20
    def fun2():   #fun2=def(){}
        print(b)
    return fun2

a = fun1()
a()
a()
a()
  • 综上所述:
    • 1、函数可以作为返回值进行返回
    • 2、函数可以作为参数进行传进
    • 3、函数名本质上是一个变量名,指向函数的内存地址

08-闭包

  • 原理:一个函数嵌套一个函数,内层函数用到外层函数的局部变量,内层函数就被称为闭包
  • 作用:保留状态,实现数据隐藏。
python 复制代码
def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

c = counter()
print(c(), c())  # 输出1, 2
python 复制代码
def outer():
    a = 1

    def inner():
        #内层函数如果要改变外层函数局部变量的值,需要使用nonlocal关键字赋予权限
        nonlocal a
        a += 1
    inner()
    print(a)

    return inner

outer()

# 可以让一个变量常驻在内存当中
# 可以避免全局变量被修改

09-装饰器

  • 原理:装饰器本质上是一个闭包,作用是不改变原有函数的前提下,为函数添加新的功能,但是源代码不改变
python 复制代码
雏形:
def wrapper(目标函数):
    def inner():
        之前添加的功能
        目标函数()
        之后添加的功能
    return inner
    
  • 作用:无侵入式增强功能(如用户登录、日志、计时)

10-装饰器参数

  • 原理:装饰器本身支持参数传递。
  • 作用:动态配置装饰器行为。
python 复制代码
def guanjia(fn):
    # 定义一个名为guanjia的装饰器函数,它接受一个函数作为参数
    print("这波传入的函数是", fn.__name__)
    # 打印传入函数的名称,方便调试和理解装饰器的工作过程

    def inner(*args, **kwargs):
        # 定义一个内部函数inner,它使用了可变参数*args和**kwargs
        # *args用于接收任意数量的位置参数,**kwargs用于接收任意数量的关键字参数
        print("开挂")
        # 在调用被装饰的函数之前,打印"开挂"信息
        fn(*args, **kwargs)
        # 调用被装饰的函数,并将接收到的参数传递给它
        print("关闭外挂")
        # 在调用被装饰的函数之后,打印"关闭外挂"信息

    return inner
    # 返回内部函数inner,这样当使用@guanjia语法时,实际上是将被装饰的函数替换为inner函数

@guanjia  # play_wz = guanjia(play_wz)
# 使用@guanjia语法将guanjia装饰器应用到play_wz函数上
# 这相当于执行了play_wz = guanjia(play_wz),将play_wz函数替换为guanjia返回的inner函数
def play_wz(uname, password):
    # 定义一个名为play_wz的函数,它接受两个参数:用户名和密码
    print("来和妲己玩耍吧")
    # 打印游戏相关的提示信息
    print(f"用户名{uname},密码是{password}")
    # 打印用户名和密码信息

@guanjia
# 使用@guanjia语法将guanjia装饰器应用到play_dnf函数上
def play_dnf(uname, pwd, g):
    # 定义一个名为play_dnf的函数,它接受三个参数:用户名、密码和技能
    print("你好啊,我是赛利亚,今天又是美好的一天")
    # 打印游戏相关的提示信息
    print(f"用户名{uname},密码是{pwd},技能是{g}")
    # 打印用户名、密码和技能信息

play_wz("zhangsan", "123456")
# 调用被装饰后的play_wz函数,传入用户名和密码
# 实际执行的是inner函数,会先打印"开挂",然后调用原始的play_wz函数,最后打印"关闭外挂"

play_dnf("lisi", "lisisi", "吹")
# 调用被装饰后的play_dnf函数,传入用户名、密码和技能
# 同样会先打印"开挂",然后调用原始的play_dnf函数,最后打印"关闭外挂"
  • 装饰器guanjia 是一个装饰器函数,它可以在不修改原函数代码的情况下,为原函数添加额外的功能(如打印 "开挂" 和 "关闭外挂" 信息)。
  • 可变参数inner 函数使用了 *args**kwargs 可变参数,这样可以处理任意数量和类型的参数,使得装饰器可以应用到不同参数的函数上。
  • 函数调用 :调用被装饰后的函数时,实际上是调用了 inner 函数,inner 函数会在调用原函数前后执行额外的操作。

11-一个函数被多个装饰器装饰

  • 原理:装饰器按从下到上的顺序执行
python 复制代码
# 定义装饰器函数 wrapper1,它接收一个函数作为参数
def wrapper1(fn):
    # 定义内部函数 inner,用于包装被装饰的函数
    def inner(*args, **kwargs):
        # 在调用被装饰函数之前,打印特定信息
        print("11111111111111111")
        # 调用被装饰的函数,并传入参数
        fn(*args, **kwargs)
        # 在调用被装饰函数之后,打印特定信息
        print("111111111111111111")
    # 返回内部函数 inner
    return inner

# 定义装饰器函数 wrapper2,它接收一个函数作为参数
def wrapper2(fn):
    # 定义内部函数 inner,用于包装被装饰的函数
    def inner(*args, **kwargs):
        # 在调用被装饰函数之前,打印特定信息
        print("2222222222222222")
        # 调用被装饰的函数,并传入参数
        fn(*args, **kwargs)
        # 在调用被装饰函数之后,打印特定信息
        print("222222222222222222")
    # 返回内部函数 inner
    return inner

# 使用 wrapper1 装饰 wrapper2 装饰后的 target 函数
# 首先执行 @wrapper2,将 target 函数替换为 wrapper2.inner
# 然后执行 @wrapper1,将 wrapper2.inner 作为参数传入 wrapper1,得到 wrapper1.inner
@wrapper1  
@wrapper2  
# 定义目标函数 target
def target():
    # 打印函数内的信息
    print("我是函数")

# 调用被装饰后的 target 函数,实际上调用的是 wrapper1.inner
target()

# 以下是使用 time 模块的代码
# 导入 time 模块,该模块提供了各种与时间相关的函数
import time
# 打印当前的时间戳,即从 1970 年 1 月 1 日午夜(UTC)开始到现在的秒数
print(time.time())
# 让程序暂停执行 2 秒
time.sleep(2)

12-装饰器函数返回值问题

  • 装饰器 guanjia:在调用被装饰的函数前后分别打印提示信息,并返回被装饰函数的返回值
python 复制代码
# 定义一个名为guanjia的装饰器函数,它接收一个函数作为参数
def guanjia(fn):
    # 定义内部函数inner,用于包裹被装饰的函数
    def inner(*args, **kwargs):
        # 在调用被装饰函数前打印提示信息
        print("11111111111111111")
        # 调用被装饰的函数,并将其返回值赋给变量ret
        ret = fn(*args, **kwargs)
        # 在调用被装饰函数后打印提示信息
        print("111111111111111111")
        # 返回被装饰函数的返回值
        return ret
    # 返回内部函数inner
    return inner

# 定义一个名为rizhi的装饰器函数,它接收一个函数作为参数
def rizhi(fn):
    # 定义内部函数inner,用于包裹被装饰的函数
    def inner(*args, **kwargs):
        # 在调用被装饰函数前打印日志信息
        print("玩了一次游戏")
        # 调用被装饰的函数
        fn(*args, **kwargs)
    # 返回内部函数inner
    return inner

# 使用guanjia装饰器装饰play_wz函数
# 相当于执行了play_wz = guanjia(play_wz)
@guanjia
# 定义一个名为play_wz的函数,接收用户名和密码作为参数
def play_wz(uname, password):
    # 打印用户名和密码信息
    print(f"用户名是{uname},密码是{password}")
    # 打印游戏相关提示信息
    print("来和妲己玩耍吧")
    # 返回游戏相关的字符串
    return "妲己玩的很666"

# 调用被装饰后的play_wz函数,并将返回值赋给变量a
a = play_wz('gouxin', 123456)
# 打印变量a的值
print(a)

# 使用rizhi装饰器装饰yonghu函数
# 相当于执行了yonghu = rizhi(yonghu)
@rizhi
# 定义一个名为yonghu的函数,接收名字和密码作为参数
def yonghu(name, pwd):
    # 打印名字和密码信息
    print(f"名字为{name},密码是{pwd}")
    # 打印相关提示信息
    print("ljs帅到飞起")
    # 返回一个字符串
    return "蔡志恒我直接爱思了"

# 调用被装饰后的yonghu函数,并将返回值赋给变量b
b = yonghu('caizhiheng', 6666)
# 打印变量b的值
print(b)

13-高阶函数map.py

  • 原理:从可迭代对象中获取第一个元素,作为函数的参数,传入函数中,将函数执行后返回结果作为生成对象中的第一个元素,最终返回一个可迭代对象
  • 语法:
python 复制代码
 map(将来可以调用的,可迭代数据)
python 复制代码
# map()
a = map(lambda x: x * x, [1, 2, 3])  # [1,4,9]
print(list(a))
for i in a:
    print(i)

# map(将来可以调用的,可迭代数据)

'''


'''


# b = map(lambda x,y:x+y,[1,2,3],[4,5,6])
# for i in b:
#     print(i)


def f1(x, y):
    return x, y


l1 = [0, 1, 2, 3, 4, 5, 6]
l2 = ['sun', 'm', 't', 'w', 't', 'f', 's']

l3 = map(f1, l1, l2)
print(list(l3))
  • 第一个 map 示例 :使用 lambda 函数对列表 [1, 2, 3] 中的元素进行平方操作,将 map 返回的迭代器转换为列表打印后,迭代器变空,后续遍历无输出。
  • 注释掉的 map 示例 :展示了 map 处理两个可迭代对象的情况,使用 lambda 函数对两个列表对应位置元素相加。
  • 自定义函数 f1map :定义函数 f1 接受两个参数并返回元组,使用 mapf1 应用到 l1l2 对应元素上,最后将结果迭代器转换为列表打印。

14-filter函数

  • 原理:filter(func, iterable) 过滤满足条件的元素,返回迭代器。
python 复制代码
# filter()   过滤对指定的序列执行过滤

a = filter(lambda x: x % 2, [1, 2, 3, 4])
print(list(a))
# 只要成立(为真:0为假,其余数字为真),就保留

15-reduce函数

  • 原理:用上一次计算的结果作为下一次传入的x值,如果上一次没有计算结果,则将可迭代数据的强两个元素分别作为x,y传入,如果有额外数据,会作为第一次传入的x值
python 复制代码
from functools import reduce

a = reduce(lambda x, y: x + y, [1, 2, 7, 4],5)
print(a)

综合实验:设计一个工资计算系统,录入员工信息,计算员工的月薪

python 复制代码
# 设计一个工资计算系统,录入员工信息,计算员工的月薪
from abc import ABCMeta, abstractmethod


class Employee(metaclass=ABCMeta):  # 抽象类不能实例化,但是子类可以继承
    # 继承抽象类

    def __init__(self, name):
        self.name = name

    # 将这个方法变成抽象方法,对象不能直接调用,但是子类可以重写这个方法
    @abstractmethod
    def give_salary(self):
        pass


class Magnaer(Employee):
    # 创建一个部门经理类,部门经理每月固定月薪666666666666666.00元

    def give_salary(self):
        return 666666666666666.00


class Programmer(Employee):
    # 创建一个程序员类,添加一个工作时间属性为 程序员计时支付月薪,每小时2元
    # super().__init__() 就是调用父类的init方法, 同样可以使用super()去调用父类的其他方法。

    def __init__(self, name, work_hour=0):
        super(Programmer, self).__init__(name)
        self.work_hour = work_hour

    def give_salary(self):
        return self.work_hour * 2


class SalesMan(Employee):
    # 创建一个销售员类,添加一个销售员按照1元底薪加上销售额5%的提成支付月薪的销售属性

    def __init__(self, name, sales=0):
        super(SalesMan, self).__init__(name)
        self.sales = sales

    def give_salary(self):
        return self.sales * 0.05 + 1


if __name__ == '__main__':
    Salary = [Magnaer('任正非'), Programmer('马化腾'), Programmer('雷军'), Programmer('埃隆·马斯克'), SalesMan('马云'),
              SalesMan('蒂姆库克')]
    for i in Salary:
        if isinstance(i, Programmer):
            i.work_hour = float(input(f'请输入{i.name}工作时长:'))
        elif isinstance(i, SalesMan):
            i.sales = float(input(f'请输入{i.name}的销售额:'))
        print(f'{i.name}的本月月薪为¥{i.give_salary()} ')

欢迎各位彦祖与热巴畅游本人专栏与技术博客

你的三连是我最大的动力

点击➡️指向的专栏名即可闪现

➡️****渗透终极之红队攻击行动********
➡️ 动画可视化数据结构与算法
➡️ 永恒之心蓝队联纵合横防御
➡️****华为高级网络工程师********
➡️****华为高级防火墙防御集成部署********
➡️ 未授权访问漏洞横向渗透利用
➡️****逆向软件破解工程********
➡️****MYSQL REDIS 进阶实操********
➡️****红帽高级工程师
➡️
红帽系统管理员********
➡️****HVV 全国各地面试题汇总********

相关推荐
巨龙之路几秒前
Lua中的元表
java·开发语言·lua
徐行11014 分钟前
C++核心机制-this 指针传递与内存布局分析
开发语言·c++
划水哥~28 分钟前
Kotlin作用域函数
开发语言·kotlin
小臭希30 分钟前
python蓝桥杯备赛常用算法模板
开发语言·python·蓝桥杯
mosaicwang35 分钟前
dnf install openssl失败的原因和解决办法
linux·运维·开发语言·python
蹦蹦跳跳真可爱5891 小时前
Python----机器学习(基于PyTorch的乳腺癌逻辑回归)
人工智能·pytorch·python·分类·逻辑回归·学习方法
Bruce_Liuxiaowei1 小时前
基于Flask的Windows事件ID查询系统开发实践
windows·python·flask
carpell1 小时前
二叉树实战篇1
python·二叉树·数据结构与算法
HORSE RUNNING WILD2 小时前
为什么我们需要if __name__ == __main__:
linux·python·bash·学习方法
凡人的AI工具箱2 小时前
PyTorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(三)
人工智能·pytorch·python·深度学习·学习·生成对抗网络