Python基础教程--函数

1、递归函数

        1.1 递归函数,就是自己调用自己的函数。

        1.2 递归的思想:

                把一个大规模问题分解成相似的小规模问题;

                再将小规模问题分解成相似的小小规模问题。。。

# 要求定义一个递归函数,实现输出n遍"我爱python"

def rec(n:int):
    if n == 0:
        return
    else:
        print(f"{n}我爱python")
        rec(n-1)

rec(10)

 

        1.3 递归函数有三要素:

                (1) 边界条件/基线条件  < 跳出 / 结束递归的条件 >

                (2) 递归返回段  < 满足结束条件时,返回 >

                (3) 递归前进段  <不满足结束条件时,前进/继续递归 >

        1.4 递归函数小练习:

# 定义一个递归函数,求n的阶乘
# 阶乘:就是累乘,从1累乘到本身,或者从本身累乘到1
# 比如:5! = 1*2*3*4*5 = 5*4*3*2*1

def rec(n:int):
    if n==1:
        return 1
    else:
        return n * rec(n-1)

s = 5
print(rec(s))

2、嵌套函数

        2.1 函数嵌套:在一个函数的内部,还嵌套定义了另外一个函数。

        2.2 外部的我们称之为“外函数”,内部的我们称之为“内函数”。

def out_fun():
    print("外函数")
    def in_fun():
        print("内函数")
    in_fun()
    
out_fun()

        2.3 嵌套函数小练习

x = 100
def out_fun():
    # global x
    x = 200
    def in_fun():
        # global x
        # nonlocal
        x = 300
        print(f"内函数中输出:{x}")
    in_fun()
    print(f"外函数中输出:{x}")

out_fun()
print(f"函数外输出:{x}")

# 【运行结果】:
# 内函数中输出:300
# 外函数中输出:200
# 函数外输出:100

        小练习结果分析:

        通过上面的例子可以发现: 内函数局部变量 > 外函数局部变量 > 全局变量;

        对比 global 和 nonlocal:

                (1)global 修饰全局变量;

                (2)nonlocal 修饰该函数上一层的局部变量;

3、闭包函数

        3.1 闭包函数:

                如果内函数中使用了外函数的局部变量,并且外函数把内函数返回的过程就叫闭包。

        3.2 形成闭包的条件:

                (1)函数嵌套;

                (2)将内函数作为返回值返回;

                (3)内函数必须使用外函数的局部变量;

def out_fun():
    x = 100
    def in_fun():
        return x+666
    return in_fun()

print(out_fun())

4、lambda 匿名函数

        4.1 匿名函数:

                就是没有名字的函数,这种函数只使用一次;

                一般函数体只有一条语句一个返回值,用于实现简单功能。

        4.2 语法格式

                lambda 参数1, 参数2, 参数3, ... : 表达式

fun_1 = lambda *num : sum(num)
print(fun_1(1, 2, 3, 4, 5))


fun_2 = lambda **students : students
print(fun_2(zhangsan=18, lisi=20, wangwu=19))


# 使用匿名函数接收两个参数 a 和 b,返回 a、b 的较大值
fun_3 = lambda a, b: max(a, b)
print(fun_3(10, 20))


# 三元运算符
# 结果1 if 条件 else 结果2
fun_4 = lambda a, b : a if a>b else b
print(fun_4(13, 10))

        4.3 lambda 函数的特性

                (1)lambda 函数是匿名的,即它是没有名字的函数,并且自带 return;

                (2)lambda 函数可以使用任意数量的参数,但只能包含一个表达式;

                (3)lambda 函数返回一个值,这个值就是表达式的结果;

                (4)lambda 函数的生命周期很短,调用后立即被回收;

5、map函数

        5.1 作用:

                用于将一个函数应用到一个序列的每一个元素,并返回一个包含结果的迭代器。

        5.2 语法格式

                map(函数, 可迭代对象)

input_num = (1, 2, 3, 4, 5)
ret = map(str, input_num)
print(ret)          # <map object at 0x1026b2500>
print(list(ret))    # ['1', '2', '3', '4', '5']


ls = [1, 2, 3, 4, 5]
ret = list(map(lambda x : x*10, ls))
print(ret)      # [10, 20, 30, 40, 50]

6、reduce函数

        6.1 作用:

                用于对序列进行累计运算,它通常需要从 functools 模块中导入。

        6.2 语法格式

                from functools import reduce

                reduce(函数, 可迭代对象)

from functools import reduce

ls = [1, 2, 3, 4, 5]
ret_sum = reduce(lambda x, y: x+y, ls)
print(ret_sum)      # 15

ret_pro = reduce(lambda x, y: x*y, ls)
print(ret_pro)      # 120

7、filter函数

        7.1 作用:

                用于遍历序列中的每个元素,根据条件进行筛选;

                返回一个包含被筛选后结果的迭代器。

        7.2 语法格式

                filter(函数, 可迭代对象)

import random

ls = [random.randint(10, 30) for _ in range(10)]
print(ls)   # [29, 28, 19, 30, 21, 22, 13, 10, 18, 28]

ret = filter(lambda x : x%2==0, ls)
print(ret)      # <filter object at 0x100bee950>
print(list(ret))    # [28, 30, 22, 10, 18, 28]

8、排序函数

menu = [['h红烧牛肉面', 18], ['x香辣牛肉面', 16], ['a安徽板面', 15], ['c重庆小面', 20]]
# 排序
menu.sort()
print(menu)

# #【运行结果】:
# # [['a安徽板面', 15], ['c重庆小面', 20], ['h红烧牛肉面', 18], ['x香辣牛肉面', 16]]


# 按单价排序
# itemgetter:获取多维数组中某个维度的元素值
import operator

menu.sort(key=operator.itemgetter(1), reverse=True)
print(menu)

# 按单价排序,使用匿名函数lambda
menu.sort(key=lambda x:x[1], reverse=False)
print(menu)

#【运行结果】:
# [['c重庆小面', 20], ['h红烧牛肉面', 18], ['x香辣牛肉面', 16], ['a安徽板面', 15]]
# [['a安徽板面', 15], ['x香辣牛肉面', 16], ['h红烧牛肉面', 18], ['c重庆小面', 20]]

9、装饰器

        9.1 概念

                装饰器本质是一个特殊的嵌套函数;

                它接收一个函数(被装饰的函数)做参数,并返回一个新的函数(装饰后的函数);

        9.2 装饰器作用:

                在不改变原有函数(被装饰的函数)的基础上给它添加新的功能。

        9.3 基本用法

# 装饰器
def out_fun(function):
    def in_fun():
        print("挂上一颗星星")
        function()
        print("挂上一个礼物盒")
    return in_fun

# 被装饰函数
def my_tree():
    print("简简单单一棵树")


# 第一种调用方式
out_fun(my_tree)()
my_tree()

# 【运行结果】:
# 挂上一颗星星
# 简简单单一棵树
# 挂上一个礼物盒
# 简简单单一棵树

# 装饰器
def out_fun(function):
    def in_fun():
        print("挂上一颗星星")
        function()
        print("挂上一个礼物盒")
    return in_fun

# 被装饰函数
def my_tree():
    print("简简单单一棵树")


# 第二种调用方式
my_tree = out_fun(my_tree)
my_tree()

#【运行结果】:
# 挂上一颗星星
# 简简单单一棵树
# 挂上一个礼物盒

        9.4 装饰器语法糖

                语法糖是由编程语言提供的,可以让代码更加简洁、高效、易读和易写。

                语法糖不改变不会带来新的功能,也不会改变编程的结果,但是使用它会更加方便。

        9.5 装饰器语法糖格式

                @装饰器函数名

                def 被装饰函数名:

                        代码块

# 装饰器
def out_fun(function):
    def in_fun():
        print("挂上一颗星星")
        function()
        print("挂上一个礼物盒")
    return in_fun

# 被装饰函数
@out_fun
def my_tree():
    print("简简单单一棵树")

my_tree()

#【运行结果】:
# 挂上一颗星星
# 简简单单一棵树
# 挂上一个礼物盒

        9.6 被装饰函数有参数

                若被装饰函数有参数,那么装饰器的内部函数也需要有参数;

                保证在内部调用被装饰函数的时候能正确传参。

# 被装饰函数有一个参数
# 装饰器
def out_fun(function):
    def in_fun(x):
        print("挂上一颗星星")
        function(x)
        print("挂上一个礼物盒")
    return in_fun

# 被装饰函数
@out_fun
def my_tree(x):
    print(f"简简单单{x}棵树")

my_tree(3)

#【运行结果】:
# 挂上一颗星星
# 简简单单3棵树
# 挂上一个礼物盒

import time

# 被装饰函数有未知个参数
# 装饰器
def out_fun(function):
    def in_fun(*args, **kwargs):
        start = time.time()
        function(*args, **kwargs)
        end = time.time()
        print(end - start)
    return in_fun

# 被装饰函数1
@out_fun
def fun_1(x):
    time.sleep(1)
    print(x)
fun_1(1)

# 被装饰函数2
@out_fun
def fun_2(x, y, z):
    time.sleep(1)
    print(x + y + z)
fun_2(1,2,3)

#【运行结果】:
# 1
# 1.0034222602844238
# 6
# 1.0041251182556152

        9.7 装饰器带参数

        上面是被装饰函数带有参数,我们在装饰器内部函数设置参数,以保证参数的正确传递。

        现在装饰器要带有参数,而且装饰器的外部函数要接收被装饰函数的函数名,内部函数要接收被装饰函数的参数,那么为了保证装饰器参数、被装饰函数参数的正确传递,我们在装饰器外部函数再嵌套一层函数,用于接收装饰器参数。

# 装饰器
def decoration(dec_arg):
    def out_fun(function):
        def in_fun(x):
            print(dec_arg)
            print("挂上一颗星星")
            function(x)
            print("挂上一个礼物盒")
        return in_fun
    return out_fun

# 被装饰函数
@decoration("我是装饰器的参数")
def my_tree(x):
    print(f"简简单单{x}棵树")

my_tree(3)

#【运行结果】:
# 我是装饰器的参数
# 挂上一颗星星
# 简简单单3棵树
# 挂上一个礼物盒

        9.8 装饰器嵌套

                装饰器嵌套就是“被装饰函数”可以被多个装饰器装饰。

# 装饰器1
def out_fun_1(function):
    def in_fun_1(*args, **kwargs):
        print("装饰器1开始调用")
        function(*args, **kwargs)
        print("装饰器1结束调用")
    return in_fun_1

# 装饰器2
def out_fun_2(function):
    def in_fun_2(*args, **kwargs):
        print("装饰器2开始调用")
        function(*args, **kwargs)
        print("装饰器2结束调用")
    return in_fun_2

# 嵌套装饰 被装饰函数
@out_fun_1
@out_fun_2
def my_tree(x):
    print(f"{x}棵树")

my_tree(3)

#【运行结果】:
# 装饰器1开始调用
# 装饰器2开始调用
# 3棵树
# 装饰器2结束调用
# 装饰器1结束调用

        9.9 类装饰器

                除了可以自定义一个新的函数用作装饰器之外,也可以将一个类作为装饰器,为被装饰的函数添加新的功能。

                类装饰器通过实现类的 __call__ 方法,使得类的实例可以被当作函数来调用,丛而实现对其他函数的装饰。

        9.10 装饰器的常见应用

# 记录日志
# 装饰器可以用来记录函数调用的详细信息,包括调用时间、参数、返回值等

import logging

def log_decorator(func):
    def wrapper(*args, **kwargs):
        logging.basicConfig(filename='./app.log', level=logging.INFO, filemode='a',
                            format='%(name)s - %(levelname)s - %(asctime)s - %(message)s')
        logging.warning(f"calling function:{func.__name__} with args:{args} and "
                        f"kwargs:{kwargs}")
        ret = func(*args, **kwargs)
        logging.warning(f"function {func.__name__} returned: {ret}")
        return ret
    return wrapper

@log_decorator
def test(a,b):
    print(a+b)

test(18,108)

#【运行结果】:
# 126

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值