Python高级编程笔记

01.Python 装饰器

方式1:使用函数的方式给函数定义装饰器

from functools import wraps

#无参数装饰器示例代码

def simple_decorator(func):
    @wraps(func)  # 使用了@wraps(func)来装饰wrapper函数,这样可保留greet函数的原始元数据,则greet.__name__返回值为greet,无此句greet.__name__返回值为wrapper
    def wrapper(*args, **kwargs):
        print(f"执行函数 {func.__name__} 之前")
        result = func(*args, **kwargs)
        print(f"执行函数 {func.__name__} 之后")
        return result

    return wrapper


@simple_decorator
def greet(name):
    """向指定的人问好"""
    print(f"你好, {name}!")


if __name__ == "__main__":
    greet("Alice")
    print(f"函数名: {greet.__name__}")
    print(f"文档字符串: {greet.__doc__}")
from functools import wraps

'''
带参数的装饰器示例:
定义了一个名为custom_decorator的装饰器工厂函数,它接受两个参数prefix和suffix。custom_decorator函数返回一个实际的装饰器decorator,
该装饰器又返回一个包装函数wrapper。wrapper函数在调用被装饰的函数之前打印prefix,在调用之后打印suffix
'''
def custom_decorator(prefix, suffix):
    def decorator(func):   # 注意无参数装饰器和有参数装饰器这里的变化
        @wraps(func)
        def wrapper(*args, **kwargs):
            print(prefix)
            result = func(*args, **kwargs)
            print(suffix)
            return result
        return wrapper
    return decorator

@custom_decorator(prefix="开始调用函数", suffix="结束调用函数")
def greet(name):
    """向指定的人问好"""
    print(f"你好, {name}!")

if __name__ == "__main__":
    greet("Alice")
    print(f"函数名: {greet.__name__}")
    print(f"文档字符串: {greet.__doc__}")

方式2:使用类的方式给一个函数定义装饰器 

主要需要实现__init__ 和 __call__ 方法,类装饰器带参数和不带参数实现略有不同,主要在不带参数,调用方法func在__init__中传入,如带参数,则参数在__init__方法传入,调用方法func则在__call__中传入.

import time

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

    def __call__(self, *args, **kwargs):
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"Function '{self.func.__name__}' took {end_time - start_time:.6f} seconds to execute")
        return result

@TimerDecorator
def slow_function():
    time.sleep(2)

slow_function()  # 输出: Function 'slow_function' took 2.001234 seconds to execute

 

02 生成器

生成器是一种特殊的迭代器,使用yield关键字来产生值,而不是一次性返回所有值。这样可以节省内存,特别是在处理大数据集时。

不适用生成器,使用迭代器达到迭代效果的样例

class Square:
    def __init__(self,count):
        self.count = count
        self.current = 1

    '''
    __iter__ 方法返回迭代器对象本身。这意味着 Square 类的实例可以被用作迭代器。
    '''
    def __iter__(self):
        return self

    '''
    __next__ 方法返回序列中的下一个值
    '''
    def __next__(self):
        result = self.current ** 2
        if self.current >= self.count:
            raise StopIteration

        self.current += 1
        return result


s1=Square(5)
for i in s1:
    print(i)
#打印结果 1 4 9 16

 使用生成器替代迭代器 :以下代码和上数迭代器代码功能相同

def squares(count: int):
    for n in range(1, count):
        yield n ** 2


for num in squares(5):
    print(num)
#打印结果 1 4 9 16

生成器完整示例代码

def simple_generator(n):
    """生成从0到n-1的数字"""
    for i in range(n):
        yield i


def main():
    # 创建生成器对象,返回一个生成器对象 gen,而不是直接执行函数体
    gen = simple_generator(5)

    # 使用生成器对象 使用 for 循环遍历生成器对象,每次迭代时生成器函数会执行到下一个 yield 语句,并返回生成的值
    for value in gen:
        print(value) #打印 0 1 2 3 4

    # 重新创建生成器对象,因为之前的已经迭代完毕
    gen = simple_generator(5)

    # 使用生成器表达式 生成器表达式类似于列表推导式,但使用圆括号 () 而不是方括号 []。生成器表达式会生成一个生成器对象,按需生成值
    gen_expr = (x * x for x in gen)
    for value in gen_expr:
        print(value) # 打印 0 1 4 9 16


if __name__ == "__main__":
    main()

 3.Python上下文管理器

上下文管理器使用with content_manager as cm 语法实现对象在进行和退出时自动完成一些动作,每一个上下文管理器都需要实现__enter__ 方法和__exit__方法

import time


class Timer:
    def __init__(self):
        self.elapsed_time = 0

    def __enter__(self):
        self.start_time = time.time()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.end_time = time.time()
        self.elapsed_time = self.end_time - self.start_time
        print(f"Elapsed time: {self.elapsed_time:.4f} seconds")


# 使用 Timer 上下文管理器
with Timer() as timer:
    # 模拟一些耗时操作
    time.sleep(2)
print(f"Total elapsed time: {timer.elapsed_time:.4f} seconds")

4. 使用Type 创建动态类

Type可以动态生成一个类,可用于实现插件式开发,动态类的代码可来自外部的文件文本,示例如下:

method_code = '''
def greet(self):
        return f"Hello, I'm a DynamicClass"
'''

# 创建一个字典来存储动态生成的方法
methods_dict = {}

# 使用 exec 动态加载方法定义
exec(method_code, globals(), methods_dict)

# 使用 type 动态创建一个类
DynamicClass = type(
    'DynamicClass',  # 类名
    (object,),  # 父类元组
    methods_dict  # 类的属性和方法
)

# 创建类的实例
instance = DynamicClass()

# 调用类的方法
print(instance.greet())  # 输出: Hello, I'm a DynamicClass

 5.Metaclass 元类

元类是用于创建类的“类”。在 Python 中,类本身是对象,而元类是创建这些类对象的类。默认情况下,所有类都是由 type 元类创建的。通过自定义元类,你可以在类创建时自定义类的行为,例如添加属性、修改方法、注册类等。

类的继承 主要用于类之间的代码重用和多态性。

元类 主要用于自定义类的创建过程和行为,提供更高的灵活性和控制力。

class Human(type):
    @staticmethod
    def __new__(mcs, *args, **kwargs):
        class_ = super().__new__(mcs, *args)
        if kwargs:
            for name, value in kwargs.items():
                setattr(class_, name, value)
        return class_


class Person(object, metaclass=Human, country='USA', freedom=True):
    def __init__(self, name, age):
        self.name = name
        self.age = age


# 测试代码
if __name__ == "__main__":
    print(Person.country)  # 输出: USA
    print(Person.freedom)  # 输出: True

    person = Person("Alice", 30)
    print(person.name)  # 输出: Alice
    print(person.age)  # 输出: 30
    print(person.country)  # 输出: USA

 6. DataClass 数据类

Dataclasses 模块提供了一种简洁的方式来定义数据类(Data Classes),这些类主要用于存储和管理数据. dataclass 装饰器自动生成了一些特殊方法,如 __init__、__repr__ 等,使得创建和打印对象更加方便

from dataclasses import dataclass, field

@dataclass
class Person:
    name: str
    age: int
    address: str = "Unknown"  # 默认值

# 创建实例
person1 = Person("Alice", 30)
person2 = Person("Bob", 25, "New York")

print(person1)  # 输出: Person(name='Alice', age=30, address='Unknown')
print(person2)  # 输出: Person(name='Bob', age=25, address='New York')

 7. global 和 nonlocal 关键字控制变量范围

global 关键字用于在函数内部声明一个变量是全局变量。这意味着你可以在函数内部访问和修改定义在函数外部的全局变量。

nonlocal 关键字用于在嵌套函数中声明一个变量是非局部变量(即它既不是局部变量也不是全局变量,而是外层函数中的变量)。这使得你可以在内层函数中访问和修改外层函数中的变量。

# 定义一个全局变量
x = 10

def modify_global():
    global x  # 声明 x 是全局变量
    x = 20  # 修改全局变量 x 的值

print(x)  # 输出: 10
modify_global()
print(x)  # 输出: 20
#  --------------------
def outer_function():
    y = 5  # 外层函数中的变量

    def inner_function():
        nonlocal y  # 声明 y 是非局部变量
        y = 10  # 修改外层函数中的变量 y

    print(y)  # 输出: 5
    inner_function()
    print(y)  # 输出: 10

outer_function()

 8.Mixin模式

Mixin 模式是一种设计模式,它允许你通过组合多个类来创建新的功能。在 Python 中,Mixin 类通常是一些小的、可重用的类,它们提供特定的功能,但不完整到可以独立使用。这些 Mixin 类可以通过多重继承的方式被其他类使用。

# LoggingMixin 提供日志记录功能
class LoggingMixin:
    def log(self, message):
        print(f"LOG: {message}")

# PermissionMixin 提供权限验证功能
class PermissionMixin:
    def has_permission(self, permission):
        return permission in self.permissions

# 基本的 User 类
class User:
    def __init__(self, name):
        self.name = name

# 使用 Mixin 组合新的类
class AdminUser(User, LoggingMixin, PermissionMixin):
    def __init__(self, name, permissions):
        super().__init__(name)
        self.permissions = permissions

    def perform_action(self, action):
        if self.has_permission(action):
            self.log(f"{self.name} is performing {action}")
            # 执行操作...
            print(f"{self.name} performed {action}")
        else:
            self.log(f"{self.name} does not have permission to perform {action}")

# 创建 AdminUser 实例并测试
admin = AdminUser("Alice", ["read", "write", "delete"])

admin.perform_action("read")     # 输出: LOG: Alice is performing read
                                 #       Alice performed read

admin.perform_action("execute")  # 输出: LOG: Alice does not have permission to perform execute

 9. 正则表达式

基本匹配: 使用 re.findall 和正则表达式模式来查找文本中的匹配项。
替换文本: 使用 re.sub 来替换文本中的匹配项。
分割文本: 使用 re.split 来根据正则表达式模式分割文本。
搜索和匹配: 使用 re.search 和 re.findall 来搜索和查找所有匹配项。
编译正则表达式: 使用 re.compile 来编译正则表达式,以便多次使用。
处理多行文本: 使用 re.MULTILINE 标志来处理多行文本。

import re

text = "Hello, my email is example@example.com and my phone number is 123-456-7890."

# 匹配电子邮件地址
email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
emails = re.findall(email_pattern, text)
print("Emails found:", emails)  # 输出: Emails found: ['example@example.com']

# 匹配电话号码
phone_pattern = r'\d{3}-\d{3}-\d{4}'
phones = re.findall(phone_pattern, text)
print("Phone numbers found:", phones)  # 输出: Phone numbers found: ['123-456-7890']
posted @ 2025-03-27 17:10  三叶草╮  阅读(23)  评论(0)    收藏  举报