将 Python 中的函数视为您的工具箱:掌握这些技巧,解决问题轻松愉悦!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

函数是一种编程语言中的概念,用于封装可重复使用的代码块。


提示:以下是本篇文章正文内容,下面案例可供参考

一、函数是什么?

在Python中,函数是一组可重用的代码块,它接收输入参数,执行一系列操作,并返回一个结果。函数可以被多次调用,并且可以在程序中的不同位置使用。

在Python中定义一个函数使用关键字def后跟函数名和参数列表,参数列表用括号括起来。函数可以有零个或多个参数,并且可以有一个返回值。

目的:提高代码的复用,减少代码的重复编写

二、函数的定义及调用

  • def:define 定义一个函数

  • def 函数名(): pass

  • 函数名的命名规则等同于变量名

  • 冒号 开启一个语句块

  • 语句块中编写函数功能的实现

  • 调用:函数名()Eg:wake_up()

代码实例:

# 例子
# 封装一个函数:目的是为了叫醒守望tk
def wake_up():
    print("醒醒了")
    print("醒醒了,守望tk")


wake_up()


# 练习
def love():
    print("""
    中华人民共和国
    960万平方公里
    56个民族
    34个省
    """)


love()


def poem():
    print("""
    从明天起,做一个幸福的人
    喂马,劈柴,周游世界
    从明天起,关心粮食和蔬菜
    我有一所房子,面朝大海,春暖花开
    从明天起,和每一个亲人通信
    告诉他们我的幸福
    那幸福的闪电告诉我的
    我将告诉每一个人
    给每一条河每一座山取一个温暖的名字
    陌生人,我也为你祝福
    愿你有一个灿烂的前程
    愿你有情人终成眷属
    愿你在尘世获得幸福
    我只愿面朝大海,春暖花开
    """)


poem()

在Python中函数的定义和普通代码之间需要隔两行。

在这里插入图片描述

在这里插入图片描述

三、函数的形参、实参及返回值

1.形参、实参

  • 形参:形式参数:出现在函数声明中的()中,没有固定值,调用函数时,将实参赋予形参。

  • 实参:实际参数:出现在函数调用的()中

  • 形参与实参:让函数功能更加灵活,函数功能更强大

def ad(address):
    print(f"{address}是属于中国的")


ad("台湾")
ad("钓鱼岛")
ad("新疆")
ad("香港")


# 答案:
# 台湾是属于中国的
# 钓鱼岛是属于中国的
# 新疆是属于中国的
# 香港是属于中国的

def wakeup(name, num):
    for i in range(num):
        print(f"醒醒了{name}")


wakeup("守望tk", 6)
wakeup("茄子", 3)


def read(name, num):
    print(f"读的第{num}本书,书名:{name}")


read("海的女儿", 1)
read("白雪公主", 2)

上方例子的运算结果

习题

题目: 封装一个函数 求从start到stop之间相差为step的质数对

# stop + 1 - step ==>  防止最后一个质数对的最后一个质数不越界
# Eg:2,50,6:最后一个质数对为(47, 53)
def zhi_shu(start, stop, step):
    for i in range(start, stop + 1 - step):
        for j in range(2, i):
            if i % j == 0:
                break
        else:
            for k in range(2, i + step):
                if (i + step) % k == 0:
                    break
            else:
                print(f"({i}, {i + step})")


zhi_shu(2, 20, 6)

在这里插入图片描述

2.函数的返回值

  • 函数的运算结果:默认返回None,即没有返回值

  • 使用return返回结果:return之后的代码不再执行,类似break;return 可以有多个返回值,最终将多个返回值放入一个元组

def my1():
    pass


r = my1()
print(r)  # None


# return之后的代码不再执行,类似break
def my1():
    return 100
    print("00")


r = my1()
print(r)  # 100


# print("00")没有执行


def my_min(first, second):
    """
    这是一个比较大小的函数(比较小的)
    :param first: 第1个形参
    :param second: 第2个形参
    :return: 计算结果
    """
    min_value = first if first < second else second
    return min_value


r = my_min(1234, 56891)
print(r)  # 1234


# 判断是否为质数
def is_prime(n):
    """
    判断n是否为质数
    :param n: 判定的数
    :return: True为是质数 False为不是质数
    """
    for i in range(2, n):
        if n % i == 0:
            return False
    else:
        return True


print(is_prime(97))

# 1000以内相差为6的质数对
for i in range(2, 1001 - 6):
    if is_prime(i) and is_prime(i + 6):
        print(i, i + 6)


def get_prime_pairs(start, stop, step):
    """
    判定质数对
    :param start:开始
    :param stop: 结束
    :param step: 步长
    :return: 返回质数对列表
    """
    result = []
    for i in range(start, stop + 1 - step):
        if is_prime(i) and is_prime(i + step):
            result.append((i, i + step))
    return result


r = get_prime_pairs(2, 30, 6)
print(r)


# 注意:return 可以有多个返回值,最后将返回值放入一个元组
def fun():
    return 100, 200


r = fun()
print(r, type(r))
r1, r2 = fun()
print(r1, r2)


def fun():
    for i in range(10):
        if i == 5:
            return i
        print("i", i)  # 0 ~ 4


r = fun()
print("r", r)  # r 5

四、函数的调试

  • 基础调试:步过:F8;恢复:直接执行下一个断点:F9

  • 函数调试:进入:步入:进入自己定义的函数(F7),进入函数后就可以使用步过F8;退出:退出函数:将函数直接执行完(shift + F8)

五、函数变量的作用域

不推荐在循环外部使用循环内部定义的局部变量 ==> 函数内部定义的局部变量,函数外部不能使用

函数内部可以获取函数外部变量:变量已经被解释器解释,如果赋值,代表着函数内部声明了一个新的变量;新的变量和外部变量同名,函数执行结束内部变量销毁

在函数内部修改函数外部变量:使用关键字global,声明以后后续的变量都是函数外部的变量

# for中定义的临时变量i
# for循环结束i的值就是for中最后一次的值
# 不推荐在for外使用for内部定义的变量
for i in range(10):
    print(i)


def f1(m):
    # 是函数内部定义的局部变量(m, i),函数外部不能使用
    i = 10
    # m = 20
    print(i, m)


f1(20)
# print(i, m)  # 错误


a = 10


def f2():
    # 第1种情况:认为a是外部变量,可以获取
    # print(a)

    # 第2种情况:因为后续有a的赋值,所以此处认为a尚未定义就直接使用
    # print(a)
    # a = 20

    # a不是修改外部变量,而是在函数内部有一个新的变量a赋值为20,函数结束,此变量消失
    # a = 20
    # print(a)

    # 第3种情况:使用关键字global声明使用的就是外部变量
    global a
    a = 20
    print(a)


f2()

print(a)

六、参数的类型写法

1.位置参数

按照位置将实参依次赋予形参

# 位置参数
# 按照位置将实参依次赋予形参
def f1(a, b, c):
    print(a, b, c)


f1(10, 20, 30)  # 将10,20,30按照位置依次赋予a,b,c


# 10 20 30

2.默认参数

形参有默认值,调用时可以没有实参,位于所有形参的最后

def f2(a, b, c=100):
    print(a, b, c)


f2(10, 20, 30)  # 形参c被传递了实参,输出实参
f2(10, 20)  # 形参c有默认值100,即使没有实参,输出默认值


# 10 20 30
# 10 20 100

3.关键字参数

  • 通过指定将实参赋予那个形参,要求没有默认值的形参必须赋值
def f3(a, b, c=15, d=44):
    print(a, b, c, d)


f3(100, 200, d=350)


# 想要将350赋予d,c就使用默认值,但如果不使用d=,那么会把350赋予c

4.可变列表(元组)参数

  • 可以接受任意个数的参数,类型是元组,在默认值参数的前面
def f4(a, b, *args):
    print(a, b, args, type(args))


f4(10, 20, 30, 40, 50)  # 10 20 (30, 40, 50) <class 'tuple'>

5.可变字典参数

  • 可以使用关键字赋值, 关键字不能是真实形参
# 可变字典
# 可变字典参数 可以使用关键字赋值,关键字不能是真实形参
# def f5(a, b, c, d,)
def f1(a, b, *args, **kwargs):
    print(a, b, args, kwargs, type(kwargs))


f1(10, 20, 30, 40, 50, 70, d1=80)


def f1(x):
    return x


print(type(f1), f1(100))
# 10 20 (30, 40, 50, 70) {'d1': 80} <class 'dict'>
# <class 'function'> 100

七、匿名函数

  • lambda 表达式

  • 只支持最简单,最近的函数写法

  • 冒号左边是形参列表,冒号右边是函数体,只支持基本格式

  • 匿名函数:没有名字的函数,不用起名,但是相当于起了一个变量名

  • lambda不能独立存在 ,需要作为实参赋予函数的形参

def f6(x):
    return x


print(type(f6), f6(100))

# 拉姆达
f7 = lambda: print("醒醒了")
print(type(f7))  # <class 'function'>
f7()  # 醒醒了

f8 = lambda: 100  # def f8(): return 100
print(f8(), type(f8))  # 100 <class 'function'>

f9 = lambda x: x + 20
print(f9(65), type(f9))  # 85 <class 'function'>

f10 = lambda x, y: x + y
print(f10(29, 78), type(f10))  # 107 <class 'function'>


# lambda不能独立存在,需要作为实参赋予函数的形参
def f0():
    print("守望tk")


def f11(i, f):
    for i in range(i):
        f()


f11(5, f0)  # 结果:执行五次守望tk
# 将f0函数的实现结果作为一个整体,当做一个变量使用
f11(3, lambda: print("love"))  # 执行3次love
# 相当于:
# f2 = lambda: print("love")
# f11(3, f2)


# lambda应用
# 1.
l = [1, 5, 6, 8, 3, 2]

# def f1(e):
#     return e
#
#
# l.sort(key=f1)
l.sort(key=lambda e: e)
print(l)

# 2.
l = [{"name": "小王子", "age": 18, "note": "玫瑰"},
     {"name": "一级律师", "age": 28, "note": "公理之下,正义不朽"},
     {"name": "海的女儿", "age": 16, "note": "美人鱼"},
     {"name": "全球高考", "age": 25, "note": "世界灿烂盛大,欢迎回家"}
     ]


# def f2(e):
#     """
#     确定排列规则
#     """
#     return e["age"]
#
#
# l.sort(key=f2)
l.sort(key=lambda e: e["age"])
print(l)

print(max(l, key=lambda e: e["age"]))
print(min(l, key=lambda e: e["age"]))

在这里插入图片描述

八、递归函数

必须要有递归出口,保障程序能退出来;自己调用自己

  • 递归不是高性能的,能不用就不用
  • 有深度限制:import sys,获取递归深度;sys.getrecursionlimit(),修改递归最大深度;sys.setrecursionlimit(修改值)

例题

1.计算1+2+3+4+5+…+100

# 常规方法
total = 0
for i in range(1, 101):
    total += i
print(total)


# 函数
def f(n):
    # 递归出口
    if n == 1:
        return 1
    else:
        # 自己调用自己
        return n + f(n-1)


r = f(100)
print(r)   # 5050

2.阶乘

def f1(n):
    if n == 1:
        # 递归出口
        return 1
    else:
        # 自己调用自己
        return n * f1(n-1)


r = f1(5)
print(r)   # 120
# 递归的默认最大深度为999

3.斐波那契数列

def f2(n):
    if n == 1 or n == 2:
        return 1
    else:
        return f2(n-1) + f2(n-2)


r = f2(9)
print(r)   # 34

补充:获取递归深度

import sys
# 获取递归深度
print(sys.getrecursionlimit())  # 1000
# 修改递归最大深度
# sys.setrecursionlimit(200)

九、装饰器

在Python中,装饰器是一个函数,用于修改其他函数的功能。装饰器的主要作用是在不改变被装饰函数源码的情况下,为其添加额外的功能。装饰器通过在被装饰函数之前和之后执行代码,实现对函数的包装。

装饰器的核心是闭包和语法糖

基础流程:

  • 1.定义基本函数

  • 2.编写闭包

  • 3.使用闭包加工原始函数

  • 4.给闭包添加权限校验

  • 5.函数调用

  • 使用@装饰器语法糖(备注)

在装饰器中,有两个经典案例:登录校验和时间花销

核心1:闭包

闭包三要素:

  • 1.外部函数嵌套内部函数
  • 2.外部函数可以将内部函数返回
  • 3.内部函数可以访问外部函数的局部变量

nonlocal:nonlocal的作用相当于global,但是nonlocal用于外部函数的局部变量

代码推导过程

# 正常
def f1():
    print("f1")


def f2():
    print("f2")


f1()
f2()


# 1.外部函数嵌套内部函数
# 嵌套
# 注意:内部函数的调用要在外部函数中
def f1():
    print("f1")

    def f2():
        print("f2")

    f2()


f1()  # f1   f2


# 2.外部函数可以将内部函数返回
def f1():
    print("f1")

    def f2():
        print("f2")

    return f2


r = f1()  # f1  # 因为f1的返回值为f2,所以r等同于f2
print(type(r))  # <class 'function'>  ,  r的类型为function,所以可以直接调用
r()  # f2


# 3.内部函数可以访问外部函数的局部变量
def f1():
    print("f1")
    i = 0

    def f2():
        # nonlocal的作用相当于global,但是nonlocal用于外部函数的局部变量
        nonlocal i
        i += 1
        print("f2", i)

    return f2


# r等同于f2(r内部保存了一个外部函数的变量i)
r = f1()  # f1
r()  # f2 1
r()  # f2 2
r()  # f2 3

如果不使用闭包,函数添加新功能就需要修改函数实现,重复代码很麻烦。

如同下方代码中,我们想要在“欢迎查看首页”、“欢迎查看购物车”、“欢迎查看个人中心”中添加用户校验,就需要在每一个函数中添加用户校验的代码。

提示:以下是代码解释内容,下面案例可供参考,嫌麻烦可以不看,有点累赘,只是展示一下不适用闭包的话会怎样。

def index():
    username = input("请输入用户名")
    if username == "admin":
        print("欢迎查看首页")
    else:
        print("用户校验失败")


index()


def shop_char():
    username = input("请输入用户名")
    if username == "admin":
        print("欢迎查看购物车")
    else:
        print("用户校验失败")


shop_char()


def ge_ren():
    username = input("请输入用户名")
    if username == "admin":
        print("欢迎查看个人中心")
    else:
        print("用户校验失败")


ge_ren()

完整的闭包如下方所示:

# 简单例子
def f1():
    print("f1")


def check(f):
    print("check 开始")
    # f()
    return f
    # print("check 结束")


# r = check(f1)   # check 开始
# r()   # f1
# check可以对f1进行加工,给f1添加新功能,但是没有更改f1
f1 = check(f1)
f1()


# 例子2
def f1():
    print("f1")


def check(f):
    print("check 开始")
    username = input("输入用户名")
    if username == "admin":
        return f
    else:
        print("用户校验失败")

下方是对上方的解释代码(就是那个在{“欢迎查看首页”、“欢迎查看购物车”、“欢迎查看个人中心”中添加用户校验})进行补充后的:

完整的闭包代码(带流程的,与最开始的装饰器流程对应,除了最后的语法糖)

# 1.定义基本函数
def index():
    print("欢迎来到首页")


def cart():
    print("欢迎来到购物车")


def mine():
    print("欢迎来到个人界面")


# login_required   通过闭包对f进行加工
# 2.编写闭包
# 3.使用闭包加工原始函数
# 4.给闭包添加权限校验
def login_required(f):
    def check1():
        username = input("输入用户名")
        if username == "admin":
            f()
        else:
            print("用户校验失败")

    return check1


# r相当于check
# r = login_required(index)
# 5.函数调用
index = login_required(index)
index()

cart = login_required(cart)
cart()

mine = login_required(mine)
mine()

核心2:语法糖

格式:@装饰器语法糖

将上一个代码采用语法糖,具体代码如下:

# 引入装饰器
def login_required(f):
    def check2():
        username = input("输入用户名")
        if username == "admin":
            f()
        else:
            print("用户校验失败")

    return check2


# 语法糖
@login_required
def index():
    print("欢迎来到首页")


@login_required
def cart():
    print("欢迎来到购物车")


@login_required
def mine():
    print("欢迎来到个人中心")


index()
cart()
mine()

个人练习,别看了!

# 登录校验
def login_request(f):
    def check():
        username = input("输入用户名")
        pwd = int(input("输入密码"))
        if username == "守望天空" and pwd == 123456:
            f()
        else:
            print("您的用户名或密码错误")

    return check


@login_request
def index():
    print("欢迎来到汉服知识网站")


def learn():
    print("朝代分类")
    print("秦朝")
    print("殷商")
    print("盛唐")
    print("强汉")
    print("大明")
    print("清朝")


@login_request
def my_center():
    print("欢迎来到个人中心(*^▽^*)")


index()
learn()
my_center()

经典案例2:时间花销

这一节开头介绍了装饰器的两大比较经典的案例,分别是登录校验和时间花销,登录校验在闭包和语法糖的讲解中已经涉及,下面介绍时间花销。

在前几篇的文章中介绍了一个模块和其中的一个概念叫做时间戳,不知是否还记得,本次时间花销需要用到时间戳。
具体介绍请见这篇文章:https://blog.csdn.net/hanqing_165/article/details/135509158

时间戳:time.time()

# 装饰器
def time_cost(f):
    def kx():
        start = time.time()
        f()
        print(time.time() - start)
    return kx

例题

题目:随机0-1000以内的500个数字放入列表,使用冒泡排序与选择排序对列表进行升序,编写装饰器,统计两个方法的时间开销

在这道题中请注意:生成数字放入列表L0中,但是在冒泡排序后L0是已经排好序的,再进行选择排序的时间比较不太公平,所以我们需要将L0中的数字再形成一个一模一样的新列表,这两个列表内容一样但不是一个列表

l0 = []
for i in range(500):
    l0.append(random.randint(0, 1000))

# 因为列表是可变类型
# 所以得到第一个列表以后,将第一个列表内容复制组成一个新列表
# 两个列表互不干扰
l1 = [i for i in l0]


# 装饰器
def time_cost(f):
    def kx():
        start = time.time()
        f()
        print(time.time() - start)
    return kx


# 冒泡
@time_cost
def mp():
    for k in range(0, len(l0) - 1):
        for j in range(k + 1, len(l0)):
            if l0[k] > l0[j]:
                l0[k], l0[j] = l0[j], l0[k]


# 选择排序
@time_cost
def xz():
    for m in range(len(l1) - 1):
        min_index = m
        for j in range(m + 1, len(l1)):
            if l1[min_index] > l1[j]:
                min_index = j
        if min_index != i:
            l1[m], l1[min_index] = l1[min_index], l1[m]


mp()
xz()

扩展:多个装饰器

装饰器距离函数越近越先装饰

如下方代码被注释掉的部分(# @time_cost # @login_required)这个表示了先进行登录校验,再进行时间的计算(把登录校验的时间一并算上了,如果用户一直停留在登录校验界面不往下方进行,那么时间花销将较大)

# 扩展
# 多个装饰器
def login_required(f):
    def check1():
        username = input("输入用户名")
        if username == "守望天空":
            f()

    return check1


def time_cost(f):
    def cost():
        start = time.time()
        f()
        print(f"时间花费{time.time() - start}")

    return cost


# 装饰器距离函数越近越先执行
@login_required
@time_cost
# @time_cost
# @login_required
def index():
    print("我是一个完整的函数")


index()

十、内置函数

内置函数用法
len长度
数学
abs绝对值
divmod求整除和余;第一个为整除,第二个为求余
pow次方
round四舍五入
sum求和
all所有元素都是真,结果就是真;如果内容为空,返回真
any所有元素都是假,结果才是假;如果内容为空,返回假
进制
bin将十进制转二进制
hex将十进制转换十六进制
oct将十进制转换八进制
callable可调用:函数、类名
ASCII
chr将ascii值转字符
ord将字符转ascii码值
sorted根据ascii排序
局部与全局变量
locals返回所有局部变量,在函数内部使用
globals返回全局变量
输入输出
input输入
print输出
id返回对象唯一标识
max、min最大最小
未来学习
delattr删除属性
getattr获取属性
hasattr是否有属性
setattr设置属性
"""
本次代码将会演示内置函数
"""
# Python自带的函数

# 长度
print(len("hello"))  # 5
# 绝对值
print(abs(-6))   # 6
# divmod:求整除和余
# 返回的为元组,第一个为整除,第二个为余数
print(divmod(100, 3))   # (33, 1)
# all:所有元素都为真结果为真,有一个为假,就为假
# 内容为空,结果也为True
print(all([0, 1, False]))  # False
print(all([0, 1, True]))   # False
print(all([10, 1, True]))  # True
print(all([]))        # True
# any:所有元素为假,结果才是假
# 内容为空,返回假
print(any([10, 0, False]))  # True
print(any(["", 0, False]))  # False
# bin:进制转换:将十进制转换为二进制
print(bin(10))   # 0b1010
# callable:可调用的
# 可调用的只有函数和类
print(callable(10), callable(lambda x: x))   # False True
# ASCII值
# chr:将ASCII值转字符,ord:将字符转ASCII值
print(chr(97), ord("A"))   # a 65

# 本宫乏了,实例代码没有写完,仿照着写就可以了

总结

以上就是今天要讲的内容,本文介绍了Python中函数的使用,包含了函数的定义、调用、形参实参返回值、调试、变量作用域、参数的类型写法、匿名函数、递归函数、内置函数以及装饰器等9大内容,希望能对嫩们有些帮助

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值