22. Python中的元类(Metaclasses)
实际上,Python在幕后使用 type 元类来创建 MyClass,这等价于:
MyClass = type('MyClass', (), {})
这里 type 函数的第一个参数是类名,第二个参数是一个包含父类的元组(这里为空元组,表示没有父类),第三个参数是一个包含类属性和方法的字典。
-
class MyMeta(type): def __new__(cls, name, bases, attrs): new_attrs = {} for key, value in attrs.items(): if not key.startswith('__'): new_attrs[key.upper()] = value else: new_attrs[key] = value return super().__new__(cls, name, bases, new_attrs)class MyClass(metaclass = MyMeta): def my_method(self): print('This is my method')obj = MyClass()# 这里调用的是修改后的大写属性名方法obj.MY_METHOD()
在上述代码中,自定义元类 MyMeta 的 new 方法在类创建时,将类中除了双下划线开头的属性名全部转换为大写。
-
23. 生成数据描述符(Data Descriptors)和非数据描述符(Non - data Descriptors)
-
-
class Integer: def __init__(self, name): self.name = name def __get__(self, instance, owner): if instance is None: return self return instance.__dict__[self.name] def __set__(self, instance, value): if not isinstance(value, int): raise ValueError('Expected an integer') instance.__dict__[self.name] = valueclass Point: x = Integer('x') y = Integer('y') def __init__(self, x, y): self.x = x self.y = yp = Point(1, 2)print(p.x)p.x = 10# 下面这行代码会触发 ValueError,因为 'a' 不是整数# p.x = 'a'
在上述代码中,Integer 类是一个数据描述符,用于验证赋给 Point 类中 x 和 y 属性的值是否为整数。
-
class ReadOnly: def __init__(self, name): self.name = name def __get__(self, instance, owner): if instance is None: return self return instance.__dict__[self.name]class MyClass: readonly_attr = ReadOnly('readonly_attr') def __init__(self): self.readonly_attr = 42obj = MyClass()print(obj.readonly_attr)# 这里不会触发描述符的 __set__ 方法(因为没有定义),所以可以修改实例属性obj.readonly_attr = 100 print(obj.readonly_attr)
理解数据描述符和非数据描述符的区别,对于深入掌握Python的属性访问机制和实现一些特殊的属性控制逻辑非常重要。
24. Python中的__slots__魔法
-
class MyClass: __slots__ = ('attr1', 'attr2') def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2obj = MyClass(1, 2)# 下面这行代码会报错,因为 __slots__ 中没有定义 'new_attr'# obj.new_attr = 3
25. Python 中的上下文触发装饰器(Context - Triggered Decorators)
-
-
import timefrom contextlib import contextmanager@contextmanagerdef timer(): start = time.time() try: yield finally: end = time.time() print(f”函数执行时间: {end - start} 秒”)def timeit(func): def wrapper(*args, **kwargs): with timer(): return func(*args, **kwargs) return wrapper@timeitdef long_running_function(): time.sleep(2) print(”长时间运行的函数执行完毕”)long_running_function()
在上述代码中,timer 是一个上下文管理器,timeit 是一个装饰器。timeit 装饰器在被装饰函数 long_running_function 执行时,启用 timer 上下文管理器,从而实现记录函数执行时间的功能。
-
26. Python 中的functools模块高级用法
-
from functools import partialdef power(base, exponent): return base ** exponentsquare = partial(power, exponent = 2)cube = partial(power, exponent = 3)print(square(5)) print(cube(3))
在上述代码中,partial 分别创建了 square 和 cube 函数,它们固定了 power 函数的 exponent 参数,使调用更加简洁。
-
import functools@functools.lru_cache(maxsize = 128)def fibonacci(n): if n <= 1: return n return fibonacci(n - 1) + fibonacci(n - 2)print(fibonacci(30))
在计算斐波那契数列时,lru_cache 可以避免重复计算已经计算过的数值,大大加快了计算速度。maxsize 参数指定了缓存的最大大小,设置为 None 则缓存大小无限制。
-
from functools import singledispatch@singledispatchdef print_type(arg): print(f”默认类型: {type(arg)}”)@print_type.register(int)def _(arg): print(f”整数类型: {arg}”)@print_type.register(str)def _(arg): print(f”字符串类型: {arg}”)print_type(10) print_type(”Hello”) print_type([1, 2, 3])
在上述代码中,singledispatch 装饰的 print_type 函数根据传入参数的类型,调用不同的处理函数。
27. Python 中的asyncio异步编程
-
-
import asyncioasync def my_coroutine(): print(”协程开始”) await asyncio.sleep(1) print(”协程结束”)
在上述代码中,my_coroutine 是一个协程函数,await 关键字用于暂停协程的执行,等待一个可等待对象(如 asyncio.sleep 返回的对象)完成,然后再继续执行。
-
loop = asyncio.get_event_loop()try: loop.run_until_complete(my_coroutine())finally: loop.close()
-
async def task_coroutine(task_number): print(f”任务 {task_number} 开始”) await asyncio.sleep(task_number) print(f”任务 {task_number} 结束”)async def main(): tasks = [asyncio.create_task(task_coroutine(i)) for i in range(1, 4)] await asyncio.gather(*tasks)loop = asyncio.get_event_loop()try: loop.run_until_complete(main())finally: loop.close()
在上述代码中,main 函数创建了多个任务并使用 asyncio.gather 等待所有任务完成。asyncio 在处理高并发的网络请求、实时数据处理等场景中具有显著优势。