Python的一些基础知识(1)

网站上一般只会提供一些最简单的有关Python的知识,在实践中,会遇到各种新的问题,为了能够提升对Python基础知识的掌握。这里总结了一些Python相关的基础知识。

Python中的抽象类

类是对一堆对象共同内容的抽取,那么抽象类就是对一堆类共同内容的抽取,包括属性和方法。

在Python中,可以使用abc模块来定义抽象类(Abstract Class)和抽象方法(Abstract Method)。抽象类是一种不能被实例化的类,它主要用于定义接口和提供基础的实现逻辑,而抽象方法是在抽象类中声明但没有具体实现的方法,需要在子类中进行实现。下面是一个简单的示例代码:
下面展示一个 示例代码

from abc import ABC, abstractmethod

class AbstractClassExample(ABC):

    @abstractmethod
    def abstract_method(self):
        pass

    def concrete_method(self):
        print("This is a concrete method.")

class ConcreteClassExample(AbstractClassExample):

    def abstract_method(self):
        print("Implementation of abstract_method.")

# 无法实例化抽象类
# example = AbstractClassExample()

# 可以实例化具体类
example = ConcreteClassExample()

# 调用抽象方法和具体方法
example.abstract_method()
example.concrete_method()

由此,我们可以得出抽象类的特点

  • 抽象类必须包含一个或多个抽象方法,也可以包含普通方法。
  • 抽象类的抽象方法,在抽象类中并不作实现。
  • 抽象类不能被实例化。
  • 抽象类的子类要想进行实例化,必须先实现抽象父类中的所有抽象方法。

主要用途

  • 定义接口:抽象类可以用于定义一组接口或契约,规定了子类需要实现的方法。通过继承抽象类并实现其中的抽象方法,可以确保子类具有相同的接口,从而达到一致性和可替换性的目的。

  • 强制子类实现方法:抽象类中的抽象方法必须在子类中进行实现。通过定义抽象方法,抽象类可以强制子类提供特定的行为或具体实现。这有助于确保子类的一致性,并使代码更易于维护和扩展。

  • 提供默认实现:抽象类可以包含具体的方法实现,这些方法在子类中可直接使用。这样,子类只需要实现抽象方法或覆盖需要定制的方法,而不需要重新实现所有方法。抽象类可以提供一些通用的功能,以减少重复代码。

  • 类型检查和文档提示:抽象类可以用于对代码进行类型检查和提供文档提示。通过声明抽象类作为参数、返回值或变量类型,可以在静态类型检查工具(如mypy)或IDE中获得更好的代码检查和自动完成功能。

总而言之,抽象类提供了一种结构化和规范化的方式来定义类的接口和行为。它们鼓励代码的模块化、可维护性和可扩展性,并提供了一些便利的功能,如强制实现、默认实现和类型检查。通过使用抽象类,可以更好地组织和设计代码,并使代码更具可读性和可重用性。

闭包

闭包是指一个函数对象,它可以访问该函数定义所在的环境中的变量,即使在函数被调用并返回之后,这些变量仍然存在于内存中。闭包可以看作是函数和其相关的引用环境组成的一个整体,它可以“记住”函数定义时的环境,以便在函数调用时使用。

特点

  • 闭包是一个函数对象,可以像其他函数一样进行调用和传递参数。

  • 闭包可以访问外部函数中定义的变量,即使在外部函数调用结束后,这些变量仍然存在于内存中。

  • 闭包可以“记住”函数定义时的环境,以便在函数调用时使用。

实现方式

def square(x):
    def inner():
        return x ** 2
    return inner

s = square(2) # 返回一个闭包
print(s()) # 输出4

应用场景

  1. 延迟计算:闭包可以在函数调用时“记住”函数定义时的环境,可以用来实现延迟计算,即在需要计算结果时再进行计算。例如,可以定义一个计算平方的函数,但不立即进行计算,而是返回一个闭包,当闭包被调用时再进行计算。

  2. 缓存数据:闭包可以将外部函数中的变量保存在内存中,可以用来实现缓存数据的功能。例如,可以定义一个函数,每次调用时返回一个闭包,闭包可以缓存之前的计算结果,避免重复计算。

  3. 实现装饰器:装饰器是Python中常用的一种编程技巧,可以用来动态修改函数的行为。闭包可以用来实现装饰器,即将一个函数作为参数传递给另一个函数,返回一个闭包,闭包可以在调用原函数之前或之后进行一些额外的操作。

装饰器

装饰器本身是一个函数,它可以接受函数作为参数,并返回一个新的函数,被称为修饰过的函数。例如在函数执行前、执行中、执行后扩展原函数的功能;它还可以用于检查函数的参数,或者对函数的返回值进行修改等。
使用装饰器的好处:

  • 装饰器允许在不改变函数本身的情况下扩展函数的功能。
  • 使用装饰器可以让函数更简洁、复用率更好,减少重复造轮子。
    下面用一些示例代码来进一步理解和分析装饰器的作用:
    无参数传入装饰
// A code block
def my_decorator(func):
    def wrapper():
        print("执行函数前")
        func()
        print("执行函数后")
    return wrapper

@my_decorator
def say_hello():
    print("Hello world!")

say_hello()
# 打印结果   
 '''
 执行函数前
 Hello world!
 执行函数后
  '''

上述代码在函数执行前和执行后增加了一些附加操作,相当于扩展了函数的功能。
另一个示例代码
参数传入装饰

// A code block
def my_decorator(arg1, arg2):  
    def inner_decorator(func):  
        def wrapper(a, b): 
            if isinstance(arg1,(float,int)):
                a = a + arg1
                print(f'{arg1} participated in the calculation process.')
            else:
                print(f'{arg1} did not participate in the calculation process')
            if isinstance(arg2, (float,int)):
                b = b + arg2
                print(f'{arg2} participated in the calculation process.')
            else:
                print(f'{arg2} did not participate in the calculation process')  
            print("Before function call")  
            result = func(a, b)  
            print("Finished the calculation process.")  
            return result  
        return wrapper  
    return inner_decorator  
  
@my_decorator("hello", "world")  
def add_function(x1,y1):  
    print(x1+y1)  
    print("Finished an addition operation ")
add_function(1,2)
# 打印结果
'''
hello did not participate in the calculation process
world did not participate in the calculation process
Before function call
3
Finished an addition operation 
Finished the calculation process.
'''

这段代码中首先定义了一个嵌套的装饰器函数my_decorator。装饰器函数需要两个参数。定义了一个被装饰的加法函数add_function,用于计算两个数字的和。
装饰器函数的两个参数,首先判断是否是浮点数或者整数,如果是,则对函数wrapper的两个参数a和b重新分别赋值。然后将赋值后的参数传入add_function函数进行加法运算。

多个装饰器示例代码

def my_decorator1(func):
    def wrapper():
        print("执行装饰器1前")
        func()
        print("执行装饰器1后")

    return wrapper

def my_decorator2(func):
    def wrapper():
        print("执行装饰器2前")
        func()
        print("执行装饰器2后")

    return wrapper
@my_decorator1
@my_decorator2
def say_hello():
    print("Hello world!")
say_hello()

# 打印结果
'''
执行装饰器1前
执行装饰器2前
Hello world!
执行装饰器2后
执行装饰器1后
'''

上面的代码中,定义了两个装饰器my_decorator1和my_decorator2。
say_hello函数首先被my_decorator2装饰器修饰,然后再用my_decorator1修饰。在执行过程中,装饰器会按顺序执行。

除了函数装饰器,Python还支持类装饰器,它接受一个函数,并返回一个修饰后的函数。这与函数装饰器非常相似,只不过是使用类而不是函数。
下面是一个类装饰器的示例代码

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("执行函数前")
        self.func(*args, **kwargs)
        print("执行函数后")

@MyDecorator
def say_hello():
    print("Hello world")
say_hello()

上面的代码中,我们用类定义了一个装饰器MyDecorator,它有一个__init__ 方法和一个__call__方法。其中,__init__方法接收一个函数作为参数,并存储在self.func变量中。__call__方法调用函数前后打印一些信息,然后调用self.func函数本身。最后,我们用@MyDecorator将函数say_hello()用MyDecorator装饰器修饰。

装饰器的应用场景

  • 日志记录:使用装饰器来记录函数的调用过程,包括函数名称、参数和返回值等。

  • 缓存数据:使用装饰器来缓存函数的计算结果,以加快函数的执行速度。

  • 输入检查:使用装饰器来检查函数的输入参数是否符合要求。

  • 认证授权:使用装饰器来检查用户的权限,以确保只有授权用户才能调用函数。

回调函数(Callback Function)

回调函数是指将一个函数作为参数传递给另一个函数,并在需要时被调用的函数。

特点

  • 通过函数地址调用函数,如果函数的指针(地址)作为参数传递给另外一个函数
  • 函数的入参为函数类型
  • 在特定的事件或者条件发生时由另外一方调用,用于对该事件或者条件进行响应
  • 在参数位置,「使用函数进行传参时,尾部不需要添加()」

回调函数的实现 示例代码

def calculator(v1,v2,fn):
    result = fn(v1,v2)
    return result

def add(v1,v2):
    return v1 + v2
    
# 调用calculator,计算1+1
print(calculator(1,1,add))   

回调函数和递归函数的区别
回调函数是在一个函数中“回调函数”以参数的形式传入,并在该函数内部被调用。而递归函数是在一个函数中,调用了自己。

使用场景

  • 事件处理。在事件驱动的程序中,回调函数经常用于处理特定的事件;比如进行错误处理,对异常结果进行记录,发送警报或者执行数据恢复工作。
    示例代码片
# 比如记录错误日志、发送警报、执行恢复操作等。
def auto_task(callback):
    try:
        # 执行自动化任务的代码
        # ...
        # 如果出现错误,抛出异常
        print(1/0)
    except Exception as e:
        # 调用错误处理的回调函数
        callback(e)


def error_callback(error):
    print(f'开始执行错误数据处理:{error}')
    
auto_task(error_callback)  
  • 迭代器和生成器。回调函数可以用于实现自定义的迭代器和生成器。例如,在读取大型文件时,可以定义一个回调函数,在每次读取到一行文本时被调用。这种方式可以有效地处理大量数据,而不需要一次性将整个文件加载到内存中。

示例代码

def read_large_file(file_path, callback):
    with open(file_path, 'r') as file:
        for line in file:
            # 调用回调函数处理每一行文本
            callback(line)

# 定义回调函数来处理每一行文本
def process_line(line):
    print("Processing line:", line.strip())
 
# 使用迭代器按行读取大型文件
# 未对数据进行处理
with open('静夜思.txt','r',encoding='utf-8') as f:
  for i in f:
    print(i)
   
   
# 使用回调函数对数据进行处理       
read_large_file('静夜思.txt',process_line)

  • 定时器和事件循环。回调函数可以用于定时器和事件循环的编程。设置一个定时器,在指定的时间间隔后调用回调函数。这对于周期性任务、定时任务和事件循环非常有用。
    下面是一个示例代码
import time

def timer_callback(i):
    print(f'定时器启动,执行了第{i}次'.center(20,'*'))

def set_time(timer,callback):
    i = 0
    while True:
        time.sleep(timer)
        i +=1
        # 使用回调函数对定时器进行处理
        callback(i)
    
set_time(5,timer_callback)
  • 钩子函数。
    回调函数也可以用作钩子函数,用于在特定的代码点执行自定义的操作。

    • 允许开发人员在代码的特定位置注入自己的逻辑,以便在关键时刻执行自定义操作。提供了一种灵活的扩展机制,使应用程序可以通过插件或扩展点来自定义行为,而无需修改核心代码。
    • 可以定义一个回调函数,用于在启动时加载配置。这样,当框架或库初始化时,回调函数会被触发,并且您可以在其中加载和应用定义好的自定义配置。
    • 在case执行完毕后,需要关闭或终止时清理资源。可以定义回调函数在应用程序关闭之前执行一些必要的清理操作,如释放内存、关闭文件、断开数据库连接等。

参考

Python中装饰器的基础使用
10 个简单但超级有用的 Python 装饰器,事半功倍
Python 第十六讲:回调函数

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值