目录
内省与反射概述
内省(Introspection)和反射(Reflection)是编程语言的高级特性,允许程序在运行时检查和修改自身的结构。
基础内省概念
import inspect
import types
from typing import Any, Dict, List, Callable
class IntrospectionBasics:
"""内省基础概念演示"""
def __init__(self, value: str = "示例属性"):
self.value = value
self._private_attr = "私有属性"
self.__name_mangled = "名称修饰属性"
def public_method(self, param: int) -> str:
"""公共方法"""
return f"处理参数: {param}"
def _protected_method(self):
"""受保护方法"""
return "受保护方法被调用"
def __private_method(self):
"""私有方法"""
return "私有方法被调用"
@staticmethod
def static_method():
"""静态方法"""
return "静态方法"
@classmethod
def class_method(cls):
"""类方法"""
return f"类方法,类名: {cls.__name__}"
@property
def computed_property(self):
"""计算属性"""
return f"计算值: {len(self.value)}"
def basic_introspection_demo():
"""基础内省演示"""
print("=== 基础内省演示 ===")
obj = IntrospectionBasics("测试对象")
# 1. 类型检查
print(f"对象类型: {type(obj)}")
print(f"是否为IntrospectionBasics实例: {isinstance(obj, IntrospectionBasics)}")
print(f"类的MRO: {type(obj).__mro__}")
# 2. 属性检查
print(f"\n对象属性:")
print(f"hasattr检查value: {hasattr(obj, 'value')}")
print(f"hasattr检查non_exist: {hasattr(obj, 'non_exist')}")
print(f"getattr获取value: {getattr(obj, 'value', '默认值')}")
print(f"getattr获取non_exist: {getattr(obj, 'non_exist', '默认值')}")
# 3. 动态设置属性
setattr(obj, 'dynamic_attr', '动态设置的属性')
print(f"动态属性: {obj.dynamic_attr}")
# 4. 删除属性
delattr(obj, 'dynamic_attr')
print(f"删除后hasattr检查: {hasattr(obj, 'dynamic_attr')}")
# 5. dir()函数 - 列出对象的所有属性和方法
print(f"\ndir()结果前10个: {dir(obj)[:10]}")
# 6. vars()函数 - 返回对象的__dict__
print(f"\nvars()结果: {vars(obj)}")
# 7. callable()检查
print(f"\n可调用性检查:")
print(f"obj.public_method可调用: {callable(obj.public_method)}")
print(f"obj.value可调用: {callable(obj.value)}")
# 运行基础演示
basic_introspection_demo()
类型检查与继承关系:使用 type(obj) 获取对象的具体类型。通过 isinstance(obj, Class) 判断对象是否为某类或其子类的实例。利用 __mro__ 属性查看类的继承顺序(方法解析顺序),有助于理解多重继承。
属性操作:hasattr(obj, 'attr') 判断对象是否拥有指定属性。getattr(obj, 'attr', default) 获取属性值,支持默认值避免异常。setattr(obj, 'attr', value) 动态设置属性,灵活扩展对象功能。delattr(obj, 'attr') 删除属性,动态调整对象状态。
属性与方法的枚举:dir(obj) 返回对象所有属性和方法的列表,方便快速查看对象结构。vars(obj) 返回对象的 __dict__,即实例属性字典,便于查看实际存储的属性。
可调用性检测:callable(obj.attr) 判断某个属性是否可调用,区分方法和普通属性。
访问不同类型的方法和属性:
示例类中包含:
- 公共方法、受保护方法(单下划线)、私有方法(双下划线,名称修饰)。
- 静态方法和类方法,分别用
@staticmethod和@classmethod装饰。 - 属性装饰器(
@property)定义的计算属性。
内置内省函数详解
class BuiltinIntrospectionFunctions:
"""内置内省函数详解"""
@staticmethod
def demonstrate_id_and_is():
"""演示id()和is操作符"""
print("=== id()和is操作符 ===")
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(f"a的id: {id(a)}")
print(f"b的id: {id(b)}")
print(f"c的id: {id(c)}")
print(f"a is b: {a is b}")
print(f"a is c: {a is c}")
print(f"a == b: {a == b}")
# 小整数缓存
x = 100
y = 100
print(f"\n小整数缓存:")
print(f"x is y (100): {x is y}")
x = 1000
y = 1000
print(f"x is y (1000): {x is y}")
@staticmethod
def demonstrate_isinstance_issubclass():
"""演示isinstance()和issubclass()"""
print("\n=== isinstance()和issubclass() ===")
class Animal:
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
print(f"isinstance(dog, Dog): {isinstance(dog, Dog)}")
print(f"isinstance(dog, Animal): {isinstance(dog, Animal)}")
print(f"isinstance(dog, (Dog, Cat)): {isinstance(dog, (Dog, Cat))}")
print(f"issubclass(Dog, Animal): {issubclass(Dog, Animal)}")
print(f"issubclass(Dog, object): {issubclass(Dog, object)}")
print(f"issubclass(Dog, (Animal, object)): {issubclass(Dog, (Animal, object))}")
@staticmethod
def demonstrate_globals_locals():
"""演示globals()和locals()"""
print("\n=== globals()和locals() ===")
global_var = "全局变量"
def inner_function():
local_var = "局部变量"
print(f"局部变量数量: {len(locals())}")
print(f"局部变量: {list(locals().keys())}")
print(f"全局变量数量: {len(globals())}")
print(f"__name__: {globals().get('__name__')}")
# 通过locals()修改变量(注意:这种方式不推荐)
locals()['new_local'] = "新局部变量"
# 这不会真正创建变量,因为locals()返回的是副本
try:
print(new_local)
except NameError:
print("通过locals()修改变量失败")
inner_function()
@staticmethod
def demonstrate_exec_eval():
"""演示exec()和eval()"""
print("\n=== exec()和eval() ===")
# eval() - 执行表达式
expression = "2 + 3 * 4"
result = eval(expression)
print(f"eval('{expression}'): {result}")
# exec() - 执行语句
code = """
def dynamic_function(x, y):
return x * y + 1
result = dynamic_function(5, 6)
"""
namespace = {}
exec(code, namespace)
print(f"exec执行结果: {namespace['result']}")
# 安全考虑 - 限制可用的内置函数
safe_dict = {"__builtins__": {"len": len, "str": str}}
try:
eval("len('hello')", safe_dict)
print("安全执行成功")
except:
print("安全执行失败")
# 运行内置函数演示
introspection_funcs = BuiltinIntrospectionFunctions()
introspection_funcs.demonstrate_id_and_is()
introspection_funcs.demonstrate_isinstance_issubclass()
introspection_funcs.demonstrate_globals_locals()
introspection_funcs.demonstrate_exec_eval()
| 内省函数/操作符 | 功能描述 | 主要应用场景与说明 |
|---|---|---|
id(obj) / is | 获取对象唯一标识(内存地址);判断对象身份是否相同 | 判断变量是否引用同一对象,理解Python对象缓存机制(如小整数缓存) |
isinstance(obj, cls) / issubclass(sub, super) | 判断对象是否为某类实例;判断类是否为另一个类的子类 | 类型检查、多态实现,支持多类型和多继承判断 |
globals() / locals() | 获取当前全局和局部命名空间字典 | 查看当前作用域变量,调试和动态变量管理;注意locals()返回副本,修改无效 |
eval(expr) | 执行字符串形式的表达式并返回结果 | 动态计算表达式,快速执行简单代码片段 |
exec(code, namespace) | 执行字符串形式的代码块(语句),无返回值 | 动态定义函数、执行复杂代码,结合命名空间获取执行结果;可限制内置函数提高安全性 |
inspect模块的高级应用
函数和方法检查
import inspect
import asyncio
from typing import Callable, Any, Dict, List, Tuple
from functools import wraps
import dis
class FunctionInspector:
"""函数检查器"""
@staticmethod
def analyze_function(func: Callable) -> Dict[str, Any]:
"""分析函数的详细信息"""
result = {
"名称": func.__name__,
"模块": func.__module__,
"文档字符串": func.__doc__,
"是否为函数": inspect.isfunction(func),
"是否为方法": inspect.ismethod(func),
"是否为内置函数": inspect.isbuiltin(func),
"是否为协程函数": inspect.iscoroutinefunction(func),
"是否为生成器函数": inspect.isgeneratorfunction(func),
}
# 获取签名
try:
sig = inspect.signature(func)
result["签名"] = str(sig)
result["参数"] = {}
for param_name, param in sig.parameters.items():
result["参数"][param_name] = {
"种类": param.kind.name,
"默认值": param.default if param.default != param.empty else "无",
"注解": param.annotation if param.annotation != param.empty else "无"
}
if sig.return_annotation != sig.empty:
result["返回注解"] = sig.return_annotation
except (ValueError, TypeError) as e:
result["签名错误"] = str(e)
# 获取源代码
try:
result["源文件"] = inspect.getfile(func)
result["源代码行号"] = inspect.getsourcelines(func)[1]
result["源代码"] = inspect.getsource(func)
except (OSError, TypeError):
result["源代码"] = "无法获取"
return result
@staticmethod
def demonstrate_parameter_kinds():
"""演示参数种类"""
print("=== 参数种类演示 ===")
def complex_function(
positional_only, /,
regular_param,
*args,
keyword_only,
keyword_with_default="默认值",
**kwargs
) -> str:
"""复杂函数参数示例"""
return "函数执行完成"
sig = inspect.signature(complex_function)
for param_name, param in sig.parameters.items():
print(f"参数: {param_name}")
print(f" 种类: {param.kind.name}")
print(f" 默认值: {param.default if param.default != param.empty else '无'}")
print()
return complex_function
@staticmethod
def create_function_wrapper():
"""创建函数包装器"""
print("=== 动态函数包装器 ===")
def smart_wrapper(func: Callable) -> Callable:
"""智能包装器,可以处理不同类型的函数"""
@wraps(func)
def sync_wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
print(f"参数: args={args}, kwargs={kwargs}")
# 检查参数
sig = inspect.signature(func)
try:
bound_args = sig.bind(*args, **kwargs)
bound_args.apply_defaults()
print(f"绑定参数: {bound_args.arguments}")
except TypeError as e:
print(f"参数绑定失败: {e}")
raise
result = func(*args, **kwargs)
print(f"返回结果: {result}")
return result
@wraps(func)
async def async_wrapper(*args, **kwargs):
print(f"调用异步函数: {func.__name__}")
result = await func(*args, **kwargs)
print(f"异步返回结果: {result}")
return result
# 根据函数类型选择包装器
if inspect.iscoroutinefunction(func):
return async_wrapper
else:
return sync_wrapper
# 测试包装器
@smart_wrapper
def test_function(x: int, y: str = "默认") -> str:
return f"x={x}, y={y}"
@smart_wrapper
async def test_async_function(delay: float) -> str:
await asyncio.sleep(delay)
return f"异步等待了 {delay} 秒"
# 测试同步函数
result = test_function(42, "测试")
# 注意:异步函数测试需要在异步环境中运行
# asyncio.run(test_async_function(0.1))
return test_function, test_async_function
# 运行函数检查演示
inspector = FunctionInspector()
# 分析内置函数
print("=== 内置函数分析 ===")
len_analysis = inspector.analyze_function(len)
for key, value in len_analysis.items():
print(f"{key}: {value}")
print("\n")
# 演示参数种类
complex_func = inspector.demonstrate_parameter_kinds()
# 创建包装器
sync_func, async_func = inspector.create_function_wrapper()
类和模块检查
class ClassInspector:
"""类检查器"""
@staticmethod
def analyze_class(cls: type) -> Dict[str, Any]:
"""分析类的详细信息"""
result = {
"类名": cls.__name__,
"模块": cls.__module__,
"文档字符串": cls.__doc__,
"基类": [base.__name__ for base in cls.__bases__],
"MRO": [c.__name__ for c in cls.__mro__],
"是否为抽象基类": inspect.isabstract(cls),
}
# 获取类成员
members = inspect.getmembers(cls)
# 分类成员
methods = []
properties = []
attributes = []
for name, value in members:
if inspect.ismethod(value) or inspect.isfunction(value):
method_info = {
"名称": name,
"类型": "method" if inspect.ismethod(value) else "function",
"是否为静态方法": isinstance(inspect.getattr_static(cls, name), staticmethod),
"是否为类方法": isinstance(inspect.getattr_static(cls, name), classmethod),
"是否为属性": isinstance(inspect.getattr_static(cls, name), property)
}
methods.append(method_info)
elif isinstance(value, property):
properties.append({"名称": name, "文档": value.__doc__})
elif not name.startswith('__') or name.endswith('__'):
attributes.append({"名称": name, "值": str(value)[:50]})
result["方法"] = methods
result["属性"] = properties
result["其他属性"] = attributes
return result
@staticmethod
def inspect_inheritance():
"""检查继承关系"""
print("=== 继承关系检查 ===")
class Animal:
def __init__(self, name: str):
self.name = name
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
return "汪汪"
class Cat(Animal):
def make_sound(self):
return "喵喵"
class Robot:
def move(self):
return "移动"
class RobotDog(Dog, Robot):
def make_sound(self):
return "机器人汪汪"
# 检查继承关系
print(f"Dog的基类: {Dog.__bases__}")
print(f"RobotDog的基类: {RobotDog.__bases__}")
print(f"RobotDog的MRO: {[c.__name__ for c in RobotDog.__mro__]}")
# 检查方法解析
robot_dog = RobotDog("机器狗")
print(f"robot_dog.make_sound(): {robot_dog.make_sound()}")
print(f"robot_dog.move(): {robot_dog.move()}")
# 使用inspect获取类层次结构
def get_class_hierarchy(cls, level=0):
indent = " " * level
print(f"{indent}{cls.__name__}")
for base in cls.__bases__:
get_class_hierarchy(base, level + 1)
print("\nRobotDog类层次结构:")
get_class_hierarchy(RobotDog)
class ModuleInspector:
"""模块检查器"""
@staticmethod
def analyze_module(module) -> Dict[str, Any]:
"""分析模块信息"""
result = {
"模块名": module.__name__,
"文档字符串": module.__doc__,
"文件路径": getattr(module, '__file__', '内置模块'),
"包": getattr(module, '__package__', None),
}
# 获取模块成员
members = inspect.getmembers(module)
# 分类成员
functions = []
classes = []
modules = []
other = []
for name, value in members:
if not name.startswith('_'): # 跳过私有成员
if inspect.isfunction(value):
functions.append(name)
elif inspect.isclass(value):
classes.append(name)
elif inspect.ismodule(value):
modules.append(name)
else:
other.append(name)
result["函数"] = functions
result["类"] = classes
result["子模块"] = modules
result["其他"] = other
return result
@staticmethod
def find_module_dependencies():
"""查找模块依赖"""
print("=== 模块依赖分析 ===")
import sys
import json
# 分析当前已加载的模块
loaded_modules = list(sys.modules.keys())
print(f"已加载模块数量: {len(loaded_modules)}")
print(f"前10个模块: {loaded_modules[:10]}")
# 分析json模块
json_analysis = ModuleInspector.analyze_module(json)
print(f"\njson模块分析:")
for key, value in json_analysis.items():
print(f" {key}: {value}")
# 运行类和模块检查演示
class_inspector = ClassInspector()
# 分析自定义类
print("=== 自定义类分析 ===")
analysis = class_inspector.analyze_class(IntrospectionBasics)
for key, value in analysis.items():
if isinstance(value, list) and len(value) > 3:
print(f"{key}: {value[:3]}... (共{len(value)}项)")
else:
print(f"{key}: {value}")
print("\n")
# 检查继承关系
class_inspector.inspect_inheritance()
print("\n")
# 模块检查
module_inspector = ModuleInspector()
module_inspector.find_module_dependencies()
调用栈检查
class CallStackInspector:
"""调用栈检查器"""
@staticmethod
def examine_call_stack():
"""检查调用栈"""
print("=== 调用栈检查 ===")
def level3_function():
print("在level3_function中:")
# 获取当前帧
current_frame = inspect.currentframe()
print(f"当前函数: {current_frame.f_code.co_name}")
print(f"文件: {current_frame.f_code.co_filename}")
print(f"行号: {current_frame.f_lineno}")
# 获取调用栈
stack = inspect.stack()
print(f"\n调用栈深度: {len(stack)}")
for i, frame_info in enumerate(stack[:5]): # 只显示前5层
print(f" 层级{i}: {frame_info.function} "
f"(文件: {frame_info.filename}:{frame_info.lineno})")
# 检查调用者信息
caller_frame = current_frame.f_back
if caller_frame:
print(f"\n调用者函数: {caller_frame.f_code.co_name}")
print(f"调用者局部变量: {list(caller_frame.f_locals.keys())}")
def level2_function():
x = "level2变量"
level3_function()
def level1_function():
y = "level1变量"
level2_function()
level1_function()
@staticmethod
def create_debug_decorator():
"""创建调试装饰器"""
print("\n=== 调试装饰器 ===")
def debug_calls(func: Callable) -> Callable:
"""调试装饰器,显示函数调用信息"""
@wraps(func)
def wrapper(*args, **kwargs):
# 获取调用信息
frame = inspect.currentframe().f_back
caller_info = inspect.getframeinfo(frame)
print(f">> 调用 {func.__name__}")
print(f" 调用者: {caller_info.filename}:{caller_info.lineno}")
print(f" 参数: args={args}, kwargs={kwargs}")
try:
result = func(*args, **kwargs)
print(f" 返回: {result}")
return result
except Exception as e:
print(f" 异常: {e}")
raise
finally:
print(f"<< 退出 {func.__name__}")
return wrapper
# 测试调试装饰器
@debug_calls
def calculate(x: int, y: int) -> int:
return x * y + 1
@debug_calls
def divide(x: int, y: int) -> float:
if y == 0:
raise ValueError("除零错误")
return x / y
# 测试正常调用
result = calculate(5, 3)
# 测试异常调用
try:
divide(10, 0)
except ValueError:
pass
return calculate, divide
@staticmethod
def trace_execution():
"""跟踪代码执行"""
print("\n=== 代码执行跟踪 ===")
def trace_function(frame, event, arg):
"""跟踪函数"""
if event == 'call':
filename = frame.f_code.co_filename
func_name = frame.f_code.co_name
line_no = frame.f_lineno
# 只跟踪我们感兴趣的文件
if __file__ in filename:
print(f"CALL: {func_name} at {line_no}")
elif event == 'return':
func_name = frame.f_code.co_name
if __file__ in frame.f_code.co_filename:
print(f"RETURN: {func_name} -> {arg}")
return trace_function
def fibonacci(n: int) -> int:
"""斐波那契数列"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 设置跟踪
import sys
print("开始跟踪:")
sys.settrace(trace_function)
try:
result = fibonacci(4)
print(f"斐波那契结果: {result}")
finally:
# 停止跟踪
sys.settrace(None)
print("跟踪结束")
# 运行调用栈检查演示
stack_inspector = CallStackInspector()
stack_inspector.examine_call_stack()
# 创建调试装饰器
calc_func, div_func = stack_inspector.create_debug_decorator()
# 跟踪执行(注意:这会产生大量输出)
# stack_inspector.trace_execution()
动态代码生成与执行
字符串代码生成
from typing import Dict, Any, List, Union
import textwrap
class CodeGenerator:
"""代码生成器"""
def __init__(self):
self.indent_level = 0
self.code_lines = []
def add_line(self, line: str = ""):
"""添加代码行"""
if line:
self.code_lines.append(" " * self.indent_level + line)
else:
self.code_lines.append("")
def indent(self):
"""增加缩进"""
self.indent_level += 1
def dedent(self):
"""减少缩进"""
self.indent_level = max(0, self.indent_level - 1)
def get_code(self) -> str:
"""获取生成的代码"""
return "\n".join(self.code_lines)
def clear(self):
"""清空代码"""
self.code_lines.clear()
self.indent_level = 0
class DynamicClassGenerator:
"""动态类生成器"""
@staticmethod
def create_data_class(class_name: str, fields: Dict[str, Any]) -> str:
"""创建数据类代码"""
generator = CodeGenerator()
# 导入语句
generator.add_line("from typing import Any")
generator.add_line("from dataclasses import dataclass")
generator.add_line()
# 类定义
generator.add_line("@dataclass")
generator.add_line(f"class {class_name}:")
generator.indent()
# 添加文档字符串
generator.add_line(f'"""{class_name}数据类"""')
generator.add_line()
# 添加字段
for field_name, field_info in fields.items():
field_type = field_info.get('type', 'Any')
default_value = field_info.get('default')
if default_value is not None:
if isinstance(default_value, str):
generator.add_line(f'{field_name}: {field_type} = "{default_value}"')
else:
generator.add_line(f'{field_name}: {field_type} = {default_value}')
else:
generator.add_line(f'{field_name}: {field_type}')
# 添加自定义方法
generator.add_line()
generator.add_line("def to_dict(self) -> dict:")
generator.indent()
generator.add_line('"""转换为字典"""')
generator.add_line("return {")
generator.indent()
for field_name in fields:
generator.add_line(f'"{field_name}": self.{field_name},')
generator.dedent()
generator.add_line("}")
return generator.get_code()
@staticmethod
def create_orm_model(table_name: str, columns: Dict[str, Dict[str, Any]]) -> str:
"""创建ORM模型代码"""
generator = CodeGenerator()
# 导入语句
generator.add_line("from typing import Optional")
generator.add_line("from datetime import datetime")
generator.add_line()
# 假设的ORM基类
generator.add_line("class BaseModel:")
generator.indent()
generator.add_line("pass")
generator.dedent()
generator.add_line()
# 类定义
class_name = ''.join(word.capitalize() for word in table_name.split('_'))
generator.add_line(f"class {class_name}(BaseModel):")
generator.indent()
generator.add_line(f'"""ORM模型 - {table_name}表"""')
generator.add_line()
generator.add_line(f'__tablename__ = "{table_name}"')
generator.add_line()
# 添加列定义
for column_name, column_info in columns.items():
column_type = column_info.get('type', 'str')
nullable = column_info.get('nullable', True)
primary_key = column_info.get('primary_key', False)
type_annotation = column_type
if nullable and not primary_key:
type_annotation = f"Optional[{column_type}]"
generator.add_line(f"{column_name}: {type_annotation}")
# 添加字段描述注释
comment = column_info.get('comment')
if comment:
generator.add_line(f'# {comment}')
# 添加构造函数
generator.add_line()
generator.add_line("def __init__(self, **kwargs):")
generator.indent()
for column_name in columns:
generator.add_line(f'self.{column_name} = kwargs.get("{column_name}")')
generator.dedent()
# 添加__repr__方法
generator.add_line()
generator.add_line("def __repr__(self) -> str:")
generator.indent()
repr_fields = list(columns.keys())[:3] # 只显示前3个字段
repr_parts = [f"{field}={{self.{field}}}" for field in repr_fields]
repr_str = f"{class_name}(" + ", ".join(repr_parts) + ")"
generator.add_line(f'return f"{repr_str}"')
return generator.get_code()
class FunctionGenerator:
"""函数生成器"""
@staticmethod
def create_getter_setter(class_name: str, attributes: List[str]) -> str:
"""生成getter和setter方法"""
generator = CodeGenerator()
generator.add_line(f"class {class_name}:")
generator.indent()
# 构造函数
generator.add_line("def __init__(self):")
generator.indent()
for attr in attributes:
generator.add_line(f"self._{attr} = None")
generator.dedent()
generator.add_line()
# 生成getter和setter
for attr in attributes:
# Getter
generator.add_line(f"def get_{attr}(self):")
generator.indent()
generator.add_line(f'"""获取{attr}属性"""')
generator.add_line(f"return self._{attr}")
generator.dedent()
generator.add_line()
# Setter
generator.add_line(f"def set_{attr}(self, value):")
generator.indent()
generator.add_line(f'"""设置{attr}属性"""')
generator.add_line(f"self._{attr} = value")
generator.dedent()
generator.add_line()
# Property
generator.add_line(f"@property")
generator.add_line(f"def {attr}(self):")
generator.indent()
generator.add_line(f"return self._{attr}")
generator.dedent()
generator.add_line()
generator.add_line(f"@{attr}.setter")
generator.add_line(f"def {attr}(self, value):")
generator.indent()
generator.add_line(f"self._{attr} = value")
generator.dedent()
generator.add_line()
return generator.get_code()
@staticmethod
def create_validation_function(field_rules: Dict[str, Dict[str, Any]]) -> str:
"""生成数据验证函数"""
generator = CodeGenerator()
generator.add_line("def validate_data(data: dict) -> tuple[bool, list]:")
generator.indent()
generator.add_line('"""验证数据"""')
generator.add_line("errors = []")
generator.add_line()
for field_name, rules in field_rules.items():
generator.add_line(f'# 验证{field_name}')
generator.add_line(f'value = data.get("{field_name}")')
# 必填检查
if rules.get('required', False):
generator.add_line("if value is None:")
generator.indent()
generator.add_line(f'errors.append("{field_name}字段不能为空")')
generator.dedent()
generator.add_line("else:")
generator.indent()
# 类型检查
field_type = rules.get('type')
if field_type:
generator.add_line(f"if not isinstance(value, {field_type.__name__}):")
generator.indent()
generator.add_line(f'errors.append("{field_name}字段类型必须为{field_type.__name__}")')
generator.dedent()
# 长度检查
min_length = rules.get('min_length')
max_length = rules.get('max_length')
if min_length or max_length:
generator.add_line("if hasattr(value, '__len__'):")
generator.indent()
if min_length:
generator.add_line(f"if len(value) < {min_length}:")
generator.indent()
generator.add_line(f'errors.append("{field_name}长度不能小于{min_length}")')
generator.dedent()
if max_length:
generator.add_line(f"if len(value) > {max_length}:")
generator.indent()
generator.add_line(f'errors.append("{field_name}长度不能大于{max_length}")')
generator.dedent()
generator.dedent()
if rules.get('required', False):
generator.dedent()
generator.add_line()
generator.add_line("return len(errors) == 0, errors")
return generator.get_code()
# 演示代码生成
def demonstrate_code_generation():
"""演示代码生成"""
print("=== 动态代码生成演示 ===")
# 生成数据类
class_gen = DynamicClassGenerator()
user_fields = {
'id': {'type': 'int', 'default': None},
'username': {'type': 'str'},
'email': {'type': 'str'},
'age': {'type': 'int', 'default': 0},
'active': {'type': 'bool', 'default': True}
}
user_class_code = class_gen.create_data_class('User', user_fields)
print("生成的User数据类:")
print(user_class_code)
print("\n" + "="*50 + "\n")
# 执行生成的代码
exec(user_class_code, globals())
# 测试生成的类
user = User(id=1, username="张三", email="zhangsan@example.com", age=25)
print(f"创建的用户对象: {user}")
print(f"转换为字典: {user.to_dict()}")
print("\n" + "="*50 + "\n")
# 生成ORM模型
user_columns = {
'id': {'type': 'int', 'primary_key': True, 'nullable': False, 'comment': '用户ID'},
'username': {'type': 'str', 'nullable': False, 'comment': '用户名'},
'email': {'type': 'str', 'nullable': False, 'comment': '邮箱'},
'created_at': {'type': 'datetime', 'nullable': True, 'comment': '创建时间'},
'is_active': {'type': 'bool', 'nullable': False, 'comment': '是否激活'}
}
orm_code = class_gen.create_orm_model('users', user_columns)
print("生成的ORM模型:")
print(orm_code)
print("\n" + "="*50 + "\n")
# 生成getter/setter
func_gen = FunctionGenerator()
attributes = ['name', 'age', 'email']
getter_setter_code = func_gen.create_getter_setter('Person', attributes)
print("生成的Getter/Setter类:")
print(getter_setter_code)
print("\n" + "="*50 + "\n")
# 生成验证函数
validation_rules = {
'username': {'required': True, 'type': str, 'min_length': 3, 'max_length': 20},
'email': {'required': True, 'type': str, 'min_length': 5},
'age': {'required': True, 'type': int},
'password': {'required': True, 'type': str, 'min_length': 8}
}
validation_code = func_gen.create_validation_function(validation_rules)
print("生成的验证函数:")
print(validation_code)
# 执行并测试验证函数
exec(validation_code, globals())
# 测试验证
test_data1 = {
'username': 'test',
'email': 'test@example.com',
'age': 25,
'password': '12345678'
}
test_data2 = {
'username': 'ab', # 太短
'email': 'test', # 太短
'age': '25', # 错误类型
# 缺少password
}
is_valid1, errors1 = validate_data(test_data1)
print(f"\n测试数据1验证结果: {is_valid1}, 错误: {errors1}")
is_valid2, errors2 = validate_data(test_data2)
print(f"测试数据2验证结果: {is_valid2}, 错误: {errors2}")
# 运行代码生成演示
demonstrate_code_generation()
模板引擎实现
import re
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
@dataclass
class TemplateVariable:
"""模板变量"""
name: str
value: Any
filters: List[str] = None
class SimpleTemplateEngine:
"""简单模板引擎"""
def __init__(self):
self.filters = {
'upper': lambda x: str(x).upper(),
'lower': lambda x: str(x).lower(),
'capitalize': lambda x: str(x).capitalize(),
'length': lambda x: len(x) if hasattr(x, '__len__') else 0,
'default': lambda x, default='': x if x is not None else default,
'join': lambda x, sep=',': sep.join(str(i) for i in x) if hasattr(x, '__iter__') else str(x)
}
def add_filter(self, name: str, func: callable):
"""添加自定义过滤器"""
self.filters[name] = func
def render_template(self, template: str, context: Dict[str, Any]) -> str:
"""渲染模板"""
# 处理变量替换 {{ variable }}
def replace_variable(match):
var_expr = match.group(1).strip()
return self._evaluate_expression(var_expr, context)
# 处理条件语句 {% if condition %} ... {% endif %}
def replace_condition(match):
condition = match.group(1).strip()
content = match.group(2)
if self._evaluate_condition(condition, context):
return self.render_template(content, context)
return ""
# 处理循环语句 {% for item in items %} ... {% endfor %}
def replace_loop(match):
loop_expr = match.group(1).strip()
content = match.group(2)
return self._process_loop(loop_expr, content, context)
# 应用替换
result = template
# 处理循环(必须在条件之前)
loop_pattern = r'\{\%\s*for\s+([^%]+)\%\}(.*?)\{\%\s*endfor\s*\%\}'
result = re.sub(loop_pattern, replace_loop, result, flags=re.DOTALL)
# 处理条件
if_pattern = r'\{\%\s*if\s+([^%]+)\%\}(.*?)\{\%\s*endif\s*\%\}'
result = re.sub(if_pattern, replace_condition, result, flags=re.DOTALL)
# 处理变量
var_pattern = r'\{\{\s*([^}]+)\s*\}\}'
result = re.sub(var_pattern, replace_variable, result)
return result
def _evaluate_expression(self, expr: str, context: Dict[str, Any]) -> str:
"""评估表达式"""
try:
# 处理过滤器 variable|filter:arg
parts = expr.split('|')
var_name = parts[0].strip()
# 获取变量值
value = self._get_variable_value(var_name, context)
# 应用过滤器
for i in range(1, len(parts)):
filter_expr = parts[i].strip()
if ':' in filter_expr:
filter_name, filter_arg = filter_expr.split(':', 1)
filter_name = filter_name.strip()
filter_arg = filter_arg.strip().strip('\'"')
if filter_name in self.filters:
value = self.filters[filter_name](value, filter_arg)
else:
filter_name = filter_expr
if filter_name in self.filters:
value = self.filters[filter_name](value)
return str(value) if value is not None else ""
except Exception as e:
return f"[Error: {e}]"
def _get_variable_value(self, var_name: str, context: Dict[str, Any]) -> Any:
"""获取变量值,支持点号访问"""
try:
parts = var_name.split('.')
value = context
for part in parts:
if isinstance(value, dict):
value = value.get(part)
else:
value = getattr(value, part, None)
if value is None:
break
return value
except:
return None
def _evaluate_condition(self, condition: str, context: Dict[str, Any]) -> bool:
"""评估条件表达式"""
try:
# 简单的条件评估(实际实现应该更安全)
# 替换变量
for var_name, value in context.items():
condition = condition.replace(var_name, repr(value))
# 安全的eval(仅允许基本操作)
allowed_names = {"True": True, "False": False, "None": None}
return eval(condition, {"__builtins__": {}}, allowed_names)
except:
return False
def _process_loop(self, loop_expr: str, content: str, context: Dict[str, Any]) -> str:
"""处理循环"""
try:
# 解析循环表达式 "item in items"
match = re.match(r'(\w+)\s+in\s+(.+)', loop_expr)
if not match:
return "[Loop Error: Invalid syntax]"
item_name = match.group(1)
items_expr = match.group(2)
# 获取循环项
items = self._get_variable_value(items_expr, context)
if not hasattr(items, '__iter__'):
return ""
# 渲染每一项
result = []
for i, item in enumerate(items):
loop_context = context.copy()
loop_context[item_name] = item
loop_context['loop'] = {
'index': i,
'index0': i,
'index1': i + 1,
'first': i == 0,
'last': i == len(list(items)) - 1 if hasattr(items, '__len__') else False
}
rendered_content = self.render_template(content, loop_context)
result.append(rendered_content)
return ''.join(result)
except Exception as e:
return f"[Loop Error: {e}]"
class CodeTemplateEngine:
"""代码模板引擎"""
def __init__(self):
self.template_engine = SimpleTemplateEngine()
self._setup_code_filters()
def _setup_code_filters(self):
"""设置代码相关的过滤器"""
self.template_engine.add_filter('snake_case', self._to_snake_case)
self.template_engine.add_filter('camel_case', self._to_camel_case)
self.template_engine.add_filter('pascal_case', self._to_pascal_case)
self.template_engine.add_filter('indent', self._indent_code)
def _to_snake_case(self, text: str) -> str:
"""转换为蛇形命名"""
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', str(text))
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def _to_camel_case(self, text: str) -> str:
"""转换为驼峰命名"""
components = str(text).split('_')
return components[0] + ''.join(x.capitalize() for x in components[1:])
def _to_pascal_case(self, text: str) -> str:
"""转换为帕斯卡命名"""
components = str(text).split('_')
return ''.join(x.capitalize() for x in components)
def _indent_code(self, text: str, spaces: str = "4") -> str:
"""缩进代码"""
indent = " " * int(spaces)
lines = str(text).split('\n')
return '\n'.join(indent + line if line.strip() else line for line in lines)
def generate_class_code(self, class_spec: Dict[str, Any]) -> str:
"""生成类代码"""
template = '''
class {{ class_name|pascal_case }}:
"""{{ description|default:"自动生成的类" }}"""
def __init__(self{% if attributes %}, {{ attributes|join:", " }}{% endif %}):
"""构造函数"""
{% for attr in attributes %}
self.{{ attr }} = {{ attr }}
{% endfor %}
{% for method in methods %}
def {{ method.name }}(self{% if method.params %}, {{ method.params|join:", " }}{% endif %}):
"""{{ method.description|default:"自动生成的方法" }}"""
{{ method.body|default:"pass"|indent:8 }}
{% endfor %}
'''.strip()
return self.template_engine.render_template(template, class_spec)
def generate_function_code(self, func_spec: Dict[str, Any]) -> str:
"""生成函数代码"""
template = '''
def {{ function_name|snake_case }}({% if params %}{{ params|join:", " }}{% endif %}):
"""{{ description|default:"自动生成的函数" }}"""
{{ body|default:"pass"|indent:4 }}
'''.strip()
return self.template_engine.render_template(template, func_spec)
# 演示模板引擎
def demonstrate_template_engine():
"""演示模板引擎"""
print("=== 模板引擎演示 ===")
# 基础模板演示
engine = SimpleTemplateEngine()
template1 = '''
Hello, {{ name|upper }}!
Your age is {{ age }}.
{% if age >= 18 %}
You are an adult.
{% endif %}
{% if items %}
Your items:
{% for item in items %}
- {{ loop.index1 }}. {{ item|capitalize }}
{% endfor %}
{% endif %}
'''.strip()
context1 = {
'name': 'zhang san',
'age': 25,
'items': ['apple', 'banana', 'orange']
}
result1 = engine.render_template(template1, context1)
print("基础模板结果:")
print(result1)
print("\n" + "="*50 + "\n")
# 代码生成模板演示
code_engine = CodeTemplateEngine()
class_spec = {
'class_name': 'user_account',
'description': '用户账户类',
'attributes': ['username', 'email', 'password'],
'methods': [
{
'name': 'validate_email',
'description': '验证邮箱格式',
'params': [],
'body': 'import re\npattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"\nreturn re.match(pattern, self.email) is not None'
},
{
'name': 'change_password',
'description': '修改密码',
'params': ['new_password'],
'body': 'if len(new_password) >= 8:\n self.password = new_password\n return True\nreturn False'
}
]
}
class_code = code_engine.generate_class_code(class_spec)
print("生成的类代码:")
print(class_code)
print("\n" + "="*50 + "\n")
# 函数生成演示
func_spec = {
'function_name': 'CalculateSum',
'description': '计算数字列表的总和',
'params': ['numbers: list', 'start_value: int = 0'],
'body': 'total = start_value\nfor num in numbers:\n total += num\nreturn total'
}
func_code = code_engine.generate_function_code(func_spec)
print("生成的函数代码:")
print(func_code)
# 执行生成的代码
print("\n测试执行生成的代码:")
exec(func_code, globals())
result = calculate_sum([1, 2, 3, 4, 5], 10)
print(f"calculate_sum([1, 2, 3, 4, 5], 10) = {result}")
# 运行模板引擎演示
demonstrate_template_engine()
代码分析与AST操作
AST基础操作
Python的AST(Abstract Syntax Tree,抽象语法树)是Python代码经过解析后生成的一种树状数据结构,用于表示源代码的语法结构。它将代码拆解成节点,每个节点代表代码中的一个语法元素,比如表达式、语句、变量、函数定义等。
import ast
import astor # 需要安装: pip install astor
from typing import List, Dict, Any, Optional
import inspect
class ASTAnalyzer:
"""AST分析器"""
def __init__(self):
self.node_counts = {}
self.function_info = []
self.class_info = []
self.import_info = []
def parse_code(self, code: str) -> ast.AST:
"""解析代码为AST"""
try:
return ast.parse(code)
except SyntaxError as e:
print(f"语法错误: {e}")
return None
def analyze_ast(self, node: ast.AST) -> Dict[str, Any]:
"""分析AST节点"""
self._reset_analysis()
self._visit_node(node)
return {
"节点统计": self.node_counts,
"函数信息": self.function_info,
"类信息": self.class_info,
"导入信息": self.import_info
}
def _reset_analysis(self):
"""重置分析状态"""
self.node_counts.clear()
self.function_info.clear()
self.class_info.clear()
self.import_info.clear()
def _visit_node(self, node: ast.AST):
"""访问AST节点"""
node_type = type(node).__name__
self.node_counts[node_type] = self.node_counts.get(node_type, 0) + 1
# 分析特定类型的节点
if isinstance(node, ast.FunctionDef):
self._analyze_function(node)
elif isinstance(node, ast.ClassDef):
self._analyze_class(node)
elif isinstance(node, (ast.Import, ast.ImportFrom)):
self._analyze_import(node)
# 递归访问子节点
for child in ast.iter_child_nodes(node):
self._visit_node(child)
def _analyze_function(self, node: ast.FunctionDef):
"""分析函数定义"""
func_info = {
"name": node.name,
"line_number": node.lineno,
"arguments": [arg.arg for arg in node.args.args],
"defaults_count": len(node.args.defaults),
"decorators": [self._get_decorator_name(d) for d in node.decorator_list],
"docstring": ast.get_docstring(node),
"complexity": self._calculate_complexity(node)
}
self.function_info.append(func_info)
def _analyze_class(self, node: ast.ClassDef):
"""分析类定义"""
methods = []
attributes = []
for child in node.body:
if isinstance(child, ast.FunctionDef):
methods.append({
"name": child.name,
"line_number": child.lineno,
"is_private": child.name.startswith('_'),
"arguments": [arg.arg for arg in child.args.args]
})
elif isinstance(child, ast.Assign):
for target in child.targets:
if isinstance(target, ast.Name):
attributes.append(target.id)
class_info = {
"name": node.name,
"line_number": node.lineno,
"base_classes": [self._get_name(base) for base in node.bases],
"decorators": [self._get_decorator_name(d) for d in node.decorator_list],
"methods": methods,
"attributes": attributes,
"docstring": ast.get_docstring(node)
}
self.class_info.append(class_info)
def _analyze_import(self, node: ast.AST):
"""分析导入语句"""
if isinstance(node, ast.Import):
for alias in node.names:
self.import_info.append({
"type": "import",
"module": alias.name,
"alias": alias.asname,
"line_number": node.lineno
})
elif isinstance(node, ast.ImportFrom):
for alias in node.names:
self.import_info.append({
"type": "from_import",
"module": node.module,
"name": alias.name,
"alias": alias.asname,
"line_number": node.lineno
})
def _get_decorator_name(self, decorator: ast.AST) -> str:
"""获取装饰器名称"""
if isinstance(decorator, ast.Name):
return decorator.id
elif isinstance(decorator, ast.Attribute):
return f"{self._get_name(decorator.value)}.{decorator.attr}"
else:
return "complex_decorator"
def _get_name(self, node: ast.AST) -> str:
"""获取节点名称"""
if isinstance(node, ast.Name):
return node.id
elif isinstance(node, ast.Attribute):
return f"{self._get_name(node.value)}.{node.attr}"
else:
return "unknown"
def _calculate_complexity(self, node: ast.FunctionDef) -> int:
"""计算函数复杂度(简化版)"""
complexity = 1 # 基础复杂度
for child in ast.walk(node):
if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
complexity += 1
elif isinstance(child, ast.BoolOp):
complexity += len(child.values) - 1
return complexity
class ASTTransformer:
"""AST转换器"""
@staticmethod
def add_logging_to_functions(code: str) -> str:
"""为所有函数添加日志记录"""
class LoggingTransformer(ast.NodeTransformer):
def visit_FunctionDef(self, node):
# 创建日志语句
log_entry = ast.Expr(
value=ast.Call(
func=ast.Attribute(
value=ast.Name(id='logging', ctx=ast.Load()),
attr='info',
ctx=ast.Load()
),
args=[
ast.Str(s=f"调用函数: {node.name}")
],
keywords=[]
)
)
log_exit = ast.Expr(
value=ast.Call(
func=ast.Attribute(
value=ast.Name(id='logging', ctx=ast.Load()),
attr='info',
ctx=ast.Load()
),
args=[
ast.Str(s=f"退出函数: {node.name}")
],
keywords=[]
)
)
# 在函数体开头添加日志
node.body.insert(0, log_entry)
# 在函数体末尾添加日志(简化处理)
if node.body and not isinstance(node.body[-1], ast.Return):
node.body.append(log_exit)
return self.generic_visit(node)
try:
tree = ast.parse(code)
transformer = LoggingTransformer()
new_tree = transformer.visit(tree)
# 修复AST
ast.fix_missing_locations(new_tree)
# 转换回代码
return astor.to_source(new_tree)
except Exception as e:
return f"转换失败: {e}"
@staticmethod
def optimize_constants(code: str) -> str:
"""常量折叠优化"""
class ConstantFolder(ast.NodeTransformer):
def visit_BinOp(self, node):
# 先处理子节点
node = self.generic_visit(node)
# 如果两个操作数都是常量,计算结果
if isinstance(node.left, ast.Num) and isinstance(node.right, ast.Num):
left_val = node.left.n
right_val = node.right.n
try:
if isinstance(node.op, ast.Add):
result = left_val + right_val
elif isinstance(node.op, ast.Sub):
result = left_val - right_val
elif isinstance(node.op, ast.Mult):
result = left_val * right_val
elif isinstance(node.op, ast.Div):
result = left_val / right_val
else:
return node
return ast.Num(n=result)
except:
return node
return node
try:
tree = ast.parse(code)
optimizer = ConstantFolder()
new_tree = optimizer.visit(tree)
ast.fix_missing_locations(new_tree)
return astor.to_source(new_tree)
except Exception as e:
return f"优化失败: {e}"
class CodeMetrics:
"""代码度量"""
@staticmethod
def calculate_metrics(code: str) -> Dict[str, Any]:
"""计算代码度量指标"""
try:
tree = ast.parse(code)
except SyntaxError as e:
return {"error": f"语法错误: {e}"}
metrics = {
"lines_of_code": len(code.split('\n')),
"total_nodes": 0,
"functions": 0,
"classes": 0,
"imports": 0,
"complexity": 0,
"max_nesting_depth": 0,
"docstrings": 0
}
class MetricsVisitor(ast.NodeVisitor):
def __init__(self):
self.nesting_depth = 0
self.max_depth = 0
def visit(self, node):
metrics["total_nodes"] += 1
# 检查嵌套深度
if isinstance(node, (ast.If, ast.For, ast.While, ast.With, ast.Try)):
self.nesting_depth += 1
self.max_depth = max(self.max_depth, self.nesting_depth)
self.generic_visit(node)
self.nesting_depth -= 1
else:
self.generic_visit(node)
def visit_FunctionDef(self, node):
metrics["functions"] += 1
if ast.get_docstring(node):
metrics["docstrings"] += 1
# 计算函数复杂度
complexity = 1
for child in ast.walk(node):
if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
complexity += 1
metrics["complexity"] += complexity
self.generic_visit(node)
def visit_ClassDef(self, node):
metrics["classes"] += 1
if ast.get_docstring(node):
metrics["docstrings"] += 1
self.generic_visit(node)
def visit_Import(self, node):
metrics["imports"] += len(node.names)
self.generic_visit(node)
def visit_ImportFrom(self, node):
metrics["imports"] += len(node.names)
self.generic_visit(node)
visitor = MetricsVisitor()
visitor.visit(tree)
metrics["max_nesting_depth"] = visitor.max_depth
# 计算平均复杂度
if metrics["functions"] > 0:
metrics["avg_complexity"] = metrics["complexity"] / metrics["functions"]
else:
metrics["avg_complexity"] = 0
return metrics
# 演示AST操作
def demonstrate_ast_operations():
"""演示AST操作"""
print("=== AST操作演示 ===")
# 示例代码
sample_code = '''
import os
import sys
from typing import List, Dict
class Calculator:
"""简单计算器类"""
def __init__(self):
self.history = []
def add(self, a: int, b: int) -> int:
"""加法运算"""
result = a + b
self.history.append(f"{a} + {b} = {result}")
return result
def multiply(self, a: int, b: int) -> int:
"""乘法运算"""
if a == 0 or b == 0:
return 0
result = a * b
for i in range(3):
if i > 0:
result += 1
self.history.append(f"{a} * {b} = {result}")
return result
def fibonacci(n: int) -> int:
"""斐波那契数列"""
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
# 常量表达式
x = 2 + 3 * 4
y = 10 - 5
z = x + y
'''
# AST分析
analyzer = ASTAnalyzer()
tree = analyzer.parse_code(sample_code)
if tree:
analysis = analyzer.analyze_ast(tree)
print("AST分析结果:")
print(f"节点统计: {analysis['节点统计']}")
print(f"\n函数信息:")
for func in analysis['函数信息']:
print(f" - {func['name']}: 复杂度={func['complexity']}, 参数={func['arguments']}")
print(f"\n类信息:")
for cls in analysis['类信息']:
print(f" - {cls['name']}: 方法数={len(cls['methods'])}, 属性数={len(cls['attributes'])}")
print(f"\n导入信息:")
for imp in analysis['导入信息']:
print(f" - {imp}")
print("\n" + "="*50 + "\n")
# AST转换
transformer = ASTTransformer()
# 添加日志
simple_code = '''
def greet(name):
return f"Hello, {name}!"
def calculate(x, y):
return x + y
'''
logged_code = transformer.add_logging_to_functions(simple_code)
print("添加日志后的代码:")
print(logged_code)
print("\n" + "="*30 + "\n")
# 常量优化
const_code = '''
x = 2 + 3
y = 5 * 4
z = 10 - 3
result = x + y + z
'''
optimized_code = transformer.optimize_constants(const_code)
print("常量优化后的代码:")
print(optimized_code)
print("\n" + "="*50 + "\n")
# 代码度量
metrics = CodeMetrics.calculate_metrics(sample_code)
print("代码度量结果:")
for key, value in metrics.items():
print(f" {key}: {value}")
# 运行AST演示(注意:需要安装astor包)
try:
demonstrate_ast_operations()
except ImportError:
print("需要安装astor包: pip install astor")
print("AST演示跳过")
静态代码分析
import ast
import re
from typing import List, Dict, Any, Tuple, Set
from dataclasses import dataclass
from enum import Enum
class IssueLevel(Enum):
"""问题级别"""
INFO = "info"
WARNING = "warning"
ERROR = "error"
CRITICAL = "critical"
@dataclass
class CodeIssue:
"""代码问题"""
level: IssueLevel
message: str
line_number: int
column: int = 0
rule_id: str = ""
suggestion: str = ""
class StaticAnalyzer:
"""静态代码分析器"""
def __init__(self):
self.issues: List[CodeIssue] = []
self.rules = {
'naming_convention': True,
'complexity': True,
'unused_imports': True,
'line_length': True,
'docstring': True,
'security': True
}
self.max_line_length = 88
self.max_complexity = 10
def analyze_code(self, code: str, filename: str = "<string>") -> List[CodeIssue]:
"""分析代码并返回问题列表"""
self.issues.clear()
try:
tree = ast.parse(code)
# 运行各种检查
if self.rules['naming_convention']:
self._check_naming_conventions(tree)
if self.rules['complexity']:
self._check_complexity(tree)
if self.rules['unused_imports']:
self._check_unused_imports(tree, code)
if self.rules['docstring']:
self._check_docstrings(tree)
if self.rules['security']:
self._check_security_issues(tree)
if self.rules['line_length']:
self._check_line_length(code)
except SyntaxError as e:
self.issues.append(CodeIssue(
level=IssueLevel.ERROR,
message=f"语法错误: {e.msg}",
line_number=e.lineno or 0,
column=e.offset or 0,
rule_id="syntax_error"
))
return self.issues
def _check_naming_conventions(self, tree: ast.AST):
"""检查命名约定"""
class NamingChecker(ast.NodeVisitor):
def __init__(self, analyzer):
self.analyzer = analyzer
def visit_FunctionDef(self, node):
# 函数名应该使用snake_case
if not self._is_snake_case(node.name) and not node.name.startswith('__'):
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message=f"函数名 '{node.name}' 应使用snake_case格式",
line_number=node.lineno,
rule_id="function_naming",
suggestion=f"建议使用: {self._to_snake_case(node.name)}"
))
self.generic_visit(node)
def visit_ClassDef(self, node):
# 类名应该使用PascalCase
if not self._is_pascal_case(node.name):
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message=f"类名 '{node.name}' 应使用PascalCase格式",
line_number=node.lineno,
rule_id="class_naming",
suggestion=f"建议使用: {self._to_pascal_case(node.name)}"
))
self.generic_visit(node)
def visit_Name(self, node):
# 常量应该使用大写
if isinstance(node.ctx, ast.Store):
if (node.id.isupper() and '_' in node.id and
len(node.id) > 3 and not self._is_constant_format(node.id)):
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.INFO,
message=f"常量 '{node.id}' 格式可能不规范",
line_number=node.lineno,
rule_id="constant_naming"
))
self.generic_visit(node)
def _is_snake_case(self, name: str) -> bool:
return re.match(r'^[a-z_][a-z0-9_]*$', name) is not None
def _is_pascal_case(self, name: str) -> bool:
return re.match(r'^[A-Z][a-zA-Z0-9]*$', name) is not None
def _is_constant_format(self, name: str) -> bool:
return re.match(r'^[A-Z][A-Z0-9_]*$', name) is not None
def _to_snake_case(self, name: str) -> str:
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
def _to_pascal_case(self, name: str) -> str:
return ''.join(word.capitalize() for word in name.split('_'))
checker = NamingChecker(self)
checker.visit(tree)
def _check_complexity(self, tree: ast.AST):
"""检查函数复杂度"""
class ComplexityChecker(ast.NodeVisitor):
def __init__(self, analyzer):
self.analyzer = analyzer
def visit_FunctionDef(self, node):
complexity = self._calculate_complexity(node)
if complexity > self.analyzer.max_complexity:
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message=f"函数 '{node.name}' 复杂度过高: {complexity}",
line_number=node.lineno,
rule_id="high_complexity",
suggestion="考虑拆分函数或简化逻辑"
))
self.generic_visit(node)
def _calculate_complexity(self, node: ast.FunctionDef) -> int:
complexity = 1
for child in ast.walk(node):
if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
complexity += 1
elif isinstance(child, ast.BoolOp):
complexity += len(child.values) - 1
return complexity
checker = ComplexityChecker(self)
checker.visit(tree)
def _check_unused_imports(self, tree: ast.AST, code: str):
"""检查未使用的导入"""
imported_names = set()
used_names = set()
class ImportChecker(ast.NodeVisitor):
def visit_Import(self, node):
for alias in node.names:
name = alias.asname if alias.asname else alias.name
imported_names.add((name, node.lineno))
def visit_ImportFrom(self, node):
for alias in node.names:
name = alias.asname if alias.asname else alias.name
imported_names.add((name, node.lineno))
def visit_Name(self, node):
if isinstance(node.ctx, ast.Load):
used_names.add(node.id)
def visit_Attribute(self, node):
if isinstance(node.value, ast.Name):
used_names.add(node.value.id)
self.generic_visit(node)
checker = ImportChecker()
checker.visit(tree)
# 找出未使用的导入
for name, line_no in imported_names:
if name not in used_names and not name.startswith('_'):
self.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message=f"未使用的导入: {name}",
line_number=line_no,
rule_id="unused_import",
suggestion="删除未使用的导入"
))
def _check_docstrings(self, tree: ast.AST):
"""检查文档字符串"""
class DocstringChecker(ast.NodeVisitor):
def __init__(self, analyzer):
self.analyzer = analyzer
def visit_FunctionDef(self, node):
# 跳过私有函数和特殊方法
if not node.name.startswith('_'):
if not ast.get_docstring(node):
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.INFO,
message=f"函数 '{node.name}' 缺少文档字符串",
line_number=node.lineno,
rule_id="missing_docstring",
suggestion="添加描述函数功能的文档字符串"
))
self.generic_visit(node)
def visit_ClassDef(self, node):
if not ast.get_docstring(node):
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.INFO,
message=f"类 '{node.name}' 缺少文档字符串",
line_number=node.lineno,
rule_id="missing_docstring",
suggestion="添加描述类功能的文档字符串"
))
self.generic_visit(node)
checker = DocstringChecker(self)
checker.visit(tree)
def _check_security_issues(self, tree: ast.AST):
"""检查安全问题"""
class SecurityChecker(ast.NodeVisitor):
def __init__(self, analyzer):
self.analyzer = analyzer
def visit_Call(self, node):
# 检查危险的函数调用
dangerous_funcs = ['eval', 'exec', 'compile']
if isinstance(node.func, ast.Name) and node.func.id in dangerous_funcs:
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.CRITICAL,
message=f"危险函数调用: {node.func.id}",
line_number=node.lineno,
rule_id="dangerous_function",
suggestion="避免使用eval/exec等危险函数"
))
# 检查subprocess调用
if (isinstance(node.func, ast.Attribute) and
isinstance(node.func.value, ast.Name) and
node.func.value.id == 'subprocess'):
# 检查shell=True
for keyword in node.keywords:
if keyword.arg == 'shell' and isinstance(keyword.value, ast.Constant):
if keyword.value.value is True:
self.analyzer.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message="subprocess调用使用shell=True可能存在安全风险",
line_number=node.lineno,
rule_id="shell_injection",
suggestion="避免使用shell=True或确保输入已经过验证"
))
self.generic_visit(node)
checker = SecurityChecker(self)
checker.visit(tree)
def _check_line_length(self, code: str):
"""检查行长度"""
lines = code.split('\n')
for i, line in enumerate(lines, 1):
if len(line) > self.max_line_length:
self.issues.append(CodeIssue(
level=IssueLevel.WARNING,
message=f"行长度超过限制: {len(line)} > {self.max_line_length}",
line_number=i,
rule_id="line_too_long",
suggestion="将长行拆分为多行"
))
def generate_report(self) -> str:
"""生成分析报告"""
if not self.issues:
return "✅ 代码分析完成,未发现问题。"
report = []
report.append(f"📊 代码分析报告 - 发现 {len(self.issues)} 个问题\n")
# 按级别分组
issues_by_level = {}
for issue in self.issues:
level = issue.level.value
if level not in issues_by_level:
issues_by_level[level] = []
issues_by_level[level].append(issue)
# 生成汇总
level_icons = {
"critical": "🔴",
"error": "❌",
"warning": "⚠️",
"info": "ℹ️"
}
for level in ["critical", "error", "warning", "info"]:
if level in issues_by_level:
count = len(issues_by_level[level])
report.append(f"{level_icons[level]} {level.upper()}: {count}")
report.append("\n" + "="*60 + "\n")
# 详细问题列表
for level in ["critical", "error", "warning", "info"]:
if level in issues_by_level:
report.append(f"{level_icons[level]} {level.upper()}问题:")
for issue in issues_by_level[level]:
report.append(f" 📍 第{issue.line_number}行: {issue.message}")
if issue.suggestion:
report.append(f" 💡 建议: {issue.suggestion}")
if issue.rule_id:
report.append(f" 🏷️ 规则: {issue.rule_id}")
report.append("")
return "\n".join(report)
# 演示静态代码分析
def demonstrate_static_analysis():
"""演示静态代码分析"""
print("=== 静态代码分析演示 ===")
# 包含各种问题的示例代码
problematic_code = '''
import os
import sys
import unused_module
class badClassName:
def __init__(self):
self.value = 0
def BadMethodName(self):
pass
def very_complex_function_with_many_conditions(x, y, z, a, b, c):
if x > 0:
if y > 0:
if z > 0:
if a > 0:
if b > 0:
if c > 0:
for i in range(100):
for j in range(100):
if i + j > 50:
result = eval("x + y") # 危险函数
return result
return 0
def function_without_docstring():
return "hello"
# 这是一行非常非常长的代码,超过了建议的行长度限制,应该被标记为问题并建议拆分成多行来提高代码可读性
x = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
subprocess.call("rm -rf /", shell=True) # 安全问题
'''
# 运行分析
analyzer = StaticAnalyzer()
issues = analyzer.analyze_code(problematic_code)
# 生成报告
report = analyzer.generate_report()
print(report)
# 显示具体问题统计
print("问题统计:")
level_counts = {}
for issue in issues:
level = issue.level.value
level_counts[level] = level_counts.get(level, 0) + 1
for level, count in level_counts.items():
print(f" {level}: {count}")
# 运行静态分析演示
demonstrate_static_analysis()
高级反射技术
元类与动态类创建
class MetaclassDemo:
"""元类演示"""
@staticmethod
def demonstrate_basic_metaclass():
"""基础元类演示"""
print("=== 基础元类演示 ===")
class SingletonMeta(type):
"""单例元类"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
"""数据库连接类(单例)"""
def __init__(self):
self.connection_id = id(self)
print(f"创建数据库连接: {self.connection_id}")
# 测试单例
conn1 = DatabaseConnection()
conn2 = DatabaseConnection()
print(f"conn1 id: {id(conn1)}")
print(f"conn2 id: {id(conn2)}")
print(f"是否为同一对象: {conn1 is conn2}")
@staticmethod
def demonstrate_attribute_validation_metaclass():
"""属性验证元类演示"""
print("\n=== 属性验证元类演示 ===")
class ValidatedMeta(type):
"""属性验证元类"""
def __new__(mcs, name, bases, namespace):
# 为所有属性添加验证
validated_namespace = {}
for key, value in namespace.items():
if not key.startswith('_') and not callable(value):
# 创建属性验证器
validated_namespace[f'_{key}'] = None
validated_namespace[key] = mcs._create_property(key, value)
else:
validated_namespace[key] = value
return super().__new__(mcs, name, bases, validated_namespace)
@staticmethod
def _create_property(attr_name, default_value):
"""创建验证属性"""
def getter(self):
return getattr(self, f'_{attr_name}', default_value)
def setter(self, value):
# 类型验证
if default_value is not None and not isinstance(value, type(default_value)):
raise TypeError(f"{attr_name}必须是{type(default_value).__name__}类型")
# 值验证
if isinstance(value, str) and len(value) == 0:
raise ValueError(f"{attr_name}不能为空字符串")
if isinstance(value, (int, float)) and value < 0:
raise ValueError(f"{attr_name}不能为负数")
setattr(self, f'_{attr_name}', value)
return property(getter, setter)
class Person(metaclass=ValidatedMeta):
"""人员类(带验证)"""
name = "默认姓名"
age = 0
salary = 0.0
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary
def __str__(self):
return f"Person(name={self.name}, age={self.age}, salary={self.salary})"
# 测试验证
try:
person = Person("张三", 25, 5000.0)
print(f"创建成功: {person}")
# 测试类型验证
person.age = "invalid" # 应该抛出异常
except TypeError as e:
print(f"类型验证成功: {e}")
try:
# 测试值验证
person.salary = -1000 # 应该抛出异常
except ValueError as e:
print(f"值验证成功: {e}")
@staticmethod
def demonstrate_orm_metaclass():
"""ORM元类演示"""
print("\n=== ORM元类演示 ===")
class Field:
"""字段基类"""
def __init__(self, field_type, required=True, default=None):
self.field_type = field_type
self.required = required
self.default = default
class CharField(Field):
"""字符字段"""
def __init__(self, max_length=255, **kwargs):
super().__init__(str, **kwargs)
self.max_length = max_length
class IntegerField(Field):
"""整数字段"""
def __init__(self, **kwargs):
super().__init__(int, **kwargs)
class ModelMeta(type):
"""模型元类"""
def __new__(mcs, name, bases, namespace):
# 收集字段定义
fields = {}
new_namespace = {}
for key, value in namespace.items():
if isinstance(value, Field):
fields[key] = value
# 创建属性描述符
new_namespace[key] = mcs._create_field_property(key, value)
else:
new_namespace[key] = value
new_namespace['_fields'] = fields
new_namespace['_data'] = {}
return super().__new__(mcs, name, bases, new_namespace)
@staticmethod
def _create_field_property(field_name, field):
"""创建字段属性"""
def getter(self):
return self._data.get(field_name, field.default)
def setter(self, value):
# 类型验证
if value is not None and not isinstance(value, field.field_type):
raise TypeError(f"{field_name}必须是{field.field_type.__name__}类型")
# 字符串长度验证
if isinstance(field, CharField) and value and len(value) > field.max_length:
raise ValueError(f"{field_name}长度不能超过{field.max_length}")
self._data[field_name] = value
return property(getter, setter)
class Model(metaclass=ModelMeta):
"""模型基类"""
def __init__(self, **kwargs):
# 验证必填字段
for field_name, field in self._fields.items():
if field.required and field_name not in kwargs and field.default is None:
raise ValueError(f"字段{field_name}是必填的")
# 设置字段值
for field_name, value in kwargs.items():
if field_name in self._fields:
setattr(self, field_name, value)
else:
raise AttributeError(f"未知字段: {field_name}")
def to_dict(self):
"""转换为字典"""
return self._data.copy()
def __str__(self):
fields_str = ', '.join(f"{k}={v}" for k, v in self._data.items())
return f"{self.__class__.__name__}({fields_str})"
# 定义用户模型
class User(Model):
"""用户模型"""
username = CharField(max_length=50)
email = CharField(max_length=100)
age = IntegerField(required=False, default=0)
# 测试ORM
try:
user = User(username="张三", email="zhangsan@example.com", age=25)
print(f"创建用户: {user}")
print(f"用户数据: {user.to_dict()}")
# 测试验证
user.username = "a" * 60 # 应该抛出异常
except ValueError as e:
print(f"长度验证成功: {e}")
class DynamicClassFactory:
"""动态类工厂"""
@staticmethod
def create_data_class(class_name: str, fields: Dict[str, Any]) -> type:
"""动态创建数据类"""
def __init__(self, **kwargs):
for field_name, field_info in fields.items():
default_value = field_info.get('default')
value = kwargs.get(field_name, default_value)
# 类型检查
expected_type = field_info.get('type')
if expected_type and value is not None and not isinstance(value, expected_type):
raise TypeError(f"{field_name}必须是{expected_type.__name__}类型")
setattr(self, field_name, value)
def __str__(self):
field_strs = []
for field_name in fields:
value = getattr(self, field_name, None)
field_strs.append(f"{field_name}={value}")
return f"{class_name}({', '.join(field_strs)})"
def __repr__(self):
return self.__str__()
def to_dict(self):
return {field_name: getattr(self, field_name, None) for field_name in fields}
# 动态创建类
class_dict = {
'__init__': __init__,
'__str__': __str__,
'__repr__': __repr__,
'to_dict': to_dict,
'_fields': fields
}
return type(class_name, (object,), class_dict)
@staticmethod
def create_enum_class(class_name: str, values: List[str]) -> type:
"""动态创建枚举类"""
def __init__(self, value):
if value not in self._values:
raise ValueError(f"无效的枚举值: {value}")
self._value = value
def __str__(self):
return f"{class_name}.{self._value}"
def __repr__(self):
return self.__str__()
def __eq__(self, other):
if isinstance(other, self.__class__):
return self._value == other._value
return self._value == other
@property
def value(self):
return self._value
# 创建类属性
class_dict = {
'__init__': __init__,
'__str__': __str__,
'__repr__': __repr__,
'__eq__': __eq__,
'value': value,
'_values': values
}
# 添加枚举常量
for val in values:
class_dict[val.upper()] = val
return type(class_name, (object,), class_dict)
@staticmethod
def create_builder_class(target_class: type) -> type:
"""为目标类创建建造者模式类"""
def __init__(self):
self._data = {}
def build(self):
return target_class(**self._data)
# 动态创建setter方法
class_dict = {
'__init__': __init__,
'build': build
}
# 获取目标类的构造参数
import inspect
sig = inspect.signature(target_class.__init__)
for param_name, param in sig.parameters.items():
if param_name != 'self':
# 创建setter方法
def make_setter(name):
def setter(self, value):
self._data[name] = value
return self # 支持链式调用
setter.__name__ = f"set_{name}"
return setter
class_dict[f"set_{param_name}"] = make_setter(param_name)
builder_class_name = f"{target_class.__name__}Builder"
return type(builder_class_name, (object,), class_dict)
# 演示高级反射技术
def demonstrate_advanced_reflection():
"""演示高级反射技术"""
print("=== 高级反射技术演示 ===")
# 元类演示
metaclass_demo = MetaclassDemo()
metaclass_demo.demonstrate_basic_metaclass()
metaclass_demo.demonstrate_attribute_validation_metaclass()
metaclass_demo.demonstrate_orm_metaclass()
print("\n" + "="*60 + "\n")
# 动态类创建演示
factory = DynamicClassFactory()
# 创建数据类
user_fields = {
'name': {'type': str, 'default': ''},
'age': {'type': int, 'default': 0},
'email': {'type': str, 'default': ''}
}
UserClass = factory.create_data_class('User', user_fields)
user = UserClass(name="李四", age=30, email="lisi@example.com")
print(f"动态创建的用户类: {user}")
print(f"用户数据: {user.to_dict()}")
# 创建枚举类
StatusEnum = factory.create_enum_class('Status', ['active', 'inactive', 'pending'])
status = StatusEnum('active')
print(f"动态创建的枚举: {status}")
print(f"枚举值: {status.value}")
print(f"枚举常量: {StatusEnum.ACTIVE}")
# 创建建造者类
BuilderClass = factory.create_builder_class(UserClass)
builder = BuilderClass()
built_user = (builder
.set_name("王五")
.set_age(28)
.set_email("wangwu@example.com")
.build())
print(f"建造者模式创建的用户: {built_user}")
# 运行高级反射演示
demonstrate_advanced_reflection()
描述符与属性管理
class DescriptorDemo:
"""描述符演示"""
class TypedAttribute:
"""类型化属性描述符"""
def __init__(self, name: str, expected_type: type, default=None):
self.name = name
self.expected_type = expected_type
self.default = default
self.private_name = f'_{name}'
def __get__(self, obj, objtype=None):
if obj is None:
return self
return getattr(obj, self.private_name, self.default)
def __set__(self, obj, value):
if not isinstance(value, self.expected_type):
raise TypeError(f"{self.name}必须是{self.expected_type.__name__}类型")
setattr(obj, self.private_name, value)
def __delete__(self, obj):
delattr(obj, self.private_name)
class ValidatedAttribute:
"""验证属性描述符"""
def __init__(self, name: str, validator: callable = None, default=None):
self.name = name
self.validator = validator
self.default = default
self.private_name = f'_{name}'
def __get__(self, obj, objtype=None):
if obj is None:
return self
return getattr(obj, self.private_name, self.default)
def __set__(self, obj, value):
if self.validator and not self.validator(value):
raise ValueError(f"{self.name}验证失败")
setattr(obj, self.private_name, value)
def __delete__(self, obj):
delattr(obj, self.private_name)
class CachedProperty:
"""缓存属性描述符"""
def __init__(self, func):
self.func = func
self.name = func.__name__
self.__doc__ = func.__doc__
def __get__(self, obj, objtype=None):
if obj is None:
return self
# 检查缓存
cache_name = f'_cached_{self.name}'
if hasattr(obj, cache_name):
return getattr(obj, cache_name)
# 计算并缓存结果
result = self.func(obj)
setattr(obj, cache_name, result)
return result
def __set__(self, obj, value):
# 清除缓存
cache_name = f'_cached_{self.name}'
if hasattr(obj, cache_name):
delattr(obj, cache_name)
# 设置新值
setattr(obj, f'_{self.name}', value)
def __delete__(self, obj):
cache_name = f'_cached_{self.name}'
if hasattr(obj, cache_name):
delattr(obj, cache_name)
def demonstrate_descriptors():
"""演示描述符"""
print("=== 描述符演示 ===")
class Person:
"""使用描述符的人员类"""
# 类型化属性
name = DescriptorDemo.TypedAttribute('name', str, '')
age = DescriptorDemo.TypedAttribute('age', int, 0)
# 验证属性
email = ValidatedAttribute('email',
validator=lambda x: '@' in str(x) if x else True)
def __init__(self, name: str, age: int, email: str = ''):
self.name = name
self.age = age
self.email = email
@CachedProperty
def display_name(self):
"""显示名称(计算密集型属性)"""
print("计算display_name...")
return f"{self.name} ({self.age}岁)"
def __str__(self):
return f"Person(name={self.name}, age={self.age}, email={self.email})"
# 测试描述符
person = Person("张三", 25, "zhangsan@example.com")
print(f"创建人员: {person}")
# 测试缓存属性
print(f"第一次访问display_name: {person.display_name}")
print(f"第二次访问display_name: {person.display_name}") # 使用缓存
# 测试类型验证
try:
person.age = "invalid" # 应该抛出异常
except TypeError as e:
print(f"类型验证成功: {e}")
# 测试值验证
try:
person.email = "invalid_email" # 应该抛出异常
except ValueError as e:
print(f"值验证成功: {e}")
class PropertyManager:
"""属性管理器"""
def __init__(self):
self._properties = {}
self._validators = {}
self._transformers = {}
def add_property(self, name: str, default=None, validator=None, transformer=None):
"""添加动态属性"""
self._properties[name] = default
if validator:
self._validators[name] = validator
if transformer:
self._transformers[name] = transformer
# 创建属性
setattr(self.__class__, name, self._create_property(name))
def _create_property(self, name: str):
"""创建属性描述符"""
def getter(self):
return self._properties.get(name)
def setter(self, value):
# 应用转换器
if name in self._transformers:
value = self._transformers[name](value)
# 应用验证器
if name in self._validators:
if not self._validators[name](value):
raise ValueError(f"属性{name}验证失败")
self._properties[name] = value
def deleter(self):
if name in self._properties:
del self._properties[name]
return property(getter, setter, deleter, f"动态属性: {name}")
def demonstrate_property_management():
"""演示属性管理"""
print("\n=== 属性管理演示 ===")
class DynamicObject(PropertyManager):
"""动态对象"""
def __init__(self):
super().__init__()
# 添加动态属性
self.add_property('username',
validator=lambda x: len(str(x)) >= 3,
transformer=str.lower)
self.add_property('age',
default=0,
validator=lambda x: isinstance(x, int) and x >= 0)
self.add_property('tags',
default=[],
transformer=lambda x: x if isinstance(x, list) else [x])
# 测试动态对象
obj = DynamicObject()
# 设置属性
obj.username = "ZHANG_SAN" # 会被转换为小写
obj.age = 25
obj.tags = "python" # 会被转换为列表
print(f"用户名: {obj.username}")
print(f"年龄: {obj.age}")
print(f"标签: {obj.tags}")
# 测试验证
try:
obj.username = "ab" # 太短,验证失败
except ValueError as e:
print(f"验证失败: {e}")
# 运行描述符演示
demonstrate_descriptors()
demonstrate_property_management()
动态类型系统
from abc import ABC, abstractmethod
from typing import Type, Union, get_type_hints
import weakref
class TypeSystem:
"""动态类型系统"""
def __init__(self):
self._type_registry = {}
self._type_constraints = {}
self._type_converters = {}
def register_type(self, name: str, type_class: Type,
constraints: List[callable] = None,
converter: callable = None):
"""注册类型"""
self._type_registry[name] = type_class
if constraints:
self._type_constraints[name] = constraints
if converter:
self._type_converters[name] = converter
def create_typed_class(self, class_name: str,
fields: Dict[str, str]) -> Type:
"""创建类型化类"""
def __init__(self, **kwargs):
for field_name, type_name in fields.items():
value = kwargs.get(field_name)
if value is not None:
validated_value = self._validate_and_convert(field_name, type_name, value)
setattr(self, field_name, validated_value)
else:
setattr(self, field_name, None)
def __setattr__(self, name, value):
if name in fields:
type_name = fields[name]
validated_value = self._validate_and_convert(name, type_name, value)
super(type(self), self).__setattr__(name, validated_value)
else:
super(type(self), self).__setattr__(name, value)
# 创建类字典
class_dict = {
'__init__': __init__,
'__setattr__': __setattr__,
'_fields': fields,
'_type_system': self
}
return type(class_name, (object,), class_dict)
def _validate_and_convert(self, field_name: str, type_name: str, value):
"""验证和转换值"""
if type_name not in self._type_registry:
raise TypeError(f"未知类型: {type_name}")
expected_type = self._type_registry[type_name]
# 尝试转换
if type_name in self._type_converters and not isinstance(value, expected_type):
try:
value = self._type_converters[type_name](value)
except Exception as e:
raise ValueError(f"字段{field_name}转换失败: {e}")
# 类型检查
if not isinstance(value, expected_type):
raise TypeError(f"字段{field_name}必须是{expected_type.__name__}类型")
# 约束检查
if type_name in self._type_constraints:
for constraint in self._type_constraints[type_name]:
if not constraint(value):
raise ValueError(f"字段{field_name}不满足约束条件")
return value
class AdvancedMetaclass(type):
"""高级元类"""
def __new__(mcs, name, bases, namespace, **kwargs):
# 处理类型注解
annotations = namespace.get('__annotations__', {})
# 自动生成属性
for attr_name, attr_type in annotations.items():
if not attr_name.startswith('_') and attr_name not in namespace:
namespace[attr_name] = mcs._create_typed_property(attr_name, attr_type)
# 添加类型信息
namespace['_type_info'] = {
'annotations': annotations,
'creation_time': time.time(),
'metaclass': mcs.__name__
}
# 自动添加__str__方法
if '__str__' not in namespace:
namespace['__str__'] = mcs._create_str_method(annotations)
cls = super().__new__(mcs, name, bases, namespace)
# 注册类
if not hasattr(mcs, '_class_registry'):
mcs._class_registry = weakref.WeakSet()
mcs._class_registry.add(cls)
return cls
@staticmethod
def _create_typed_property(attr_name: str, attr_type: Type):
"""创建类型化属性"""
private_name = f'_{attr_name}'
def getter(self):
return getattr(self, private_name, None)
def setter(self, value):
if value is not None and not isinstance(value, attr_type):
# 尝试类型转换
try:
if attr_type == int:
value = int(value)
elif attr_type == float:
value = float(value)
elif attr_type == str:
value = str(value)
elif attr_type == bool:
value = bool(value)
else:
raise TypeError(f"无法转换为{attr_type.__name__}")
except (ValueError, TypeError):
raise TypeError(f"{attr_name}必须是{attr_type.__name__}类型")
setattr(self, private_name, value)
return property(getter, setter, doc=f"类型化属性: {attr_name} ({attr_type.__name__})")
@staticmethod
def _create_str_method(annotations: Dict[str, Type]):
"""创建__str__方法"""
def __str__(self):
class_name = self.__class__.__name__
attrs = []
for attr_name in annotations:
value = getattr(self, attr_name, None)
attrs.append(f"{attr_name}={value}")
return f"{class_name}({', '.join(attrs)})"
return __str__
@classmethod
def get_registered_classes(mcs):
"""获取注册的类"""
if hasattr(mcs, '_class_registry'):
return list(mcs._class_registry)
return []
def demonstrate_advanced_reflection():
"""演示高级反射技术"""
print("=== 高级反射技术演示 ===")
# 动态类型系统演示
type_system = TypeSystem()
# 注册类型
type_system.register_type('string', str,
constraints=[lambda x: len(x) > 0],
converter=str)
type_system.register_type('positive_int', int,
constraints=[lambda x: x > 0],
converter=int)
type_system.register_type('email', str,
constraints=[lambda x: '@' in x and '.' in x])
# 创建动态类
UserClass = type_system.create_typed_class('User', {
'name': 'string',
'age': 'positive_int',
'email': 'email'
})
# 测试动态类
try:
user = UserClass(name="张三", age="25", email="zhangsan@example.com")
print(f"创建用户成功: name={user.name}, age={user.age}, email={user.email}")
# 测试约束
user.age = -5 # 应该失败
except ValueError as e:
print(f"约束验证成功: {e}")
print("\n" + "="*50 + "\n")
# 高级元类演示
class Product(metaclass=AdvancedMetaclass):
"""产品类"""
name: str
price: float
in_stock: bool
def __init__(self, name: str, price: float, in_stock: bool = True):
self.name = name
self.price = price
self.in_stock = in_stock
# 测试自动生成的功能
product = Product("笔记本电脑", 5999.99, True)
print(f"产品信息: {product}")
print(f"类型信息: {product._type_info}")
# 测试类型转换
product.price = "6999.99" # 字符串会被自动转换为float
print(f"价格转换后: {product.price} (类型: {type(product.price)})")
# 获取注册的类
registered_classes = AdvancedMetaclass.get_registered_classes()
print(f"注册的类: {[cls.__name__ for cls in registered_classes]}")
# 运行高级反射演示
demonstrate_advanced_reflection()
总结与进阶方向
核心概念总结

| 主题 | 最佳实践示例 |
|---|---|
| 安全性考虑 | 1. 避免使用eval()和exec()处理不可信输入 2. 使用ast.literal_eval()代替eval() 3. 限制动态代码执行的命名空间 4. 验证和清理用户输入 5. 使用白名单而非黑名单进行安全检查 |
| 性能优化 | 1. 缓存反射操作的结果 2. 避免循环中重复反射 3. 使用__slots__减少内存 4. 合理使用描述符和属性 5. 使用functools.lru_cache装饰器 |
| 代码可维护性 | 1. 为动态代码添加文档 2. 使用类型注解 3. 保持反射逻辑简单 4. 提供清晰错误消息 5. 编写充分测试用例 |
| 调试技巧 | 1. 使用inspect模块查看对象 2. 利用pdb调试器 3. 记录反射操作日志 4. 使用断言验证假设 5. 创建调试装饰器跟踪调用 |

1094

被折叠的 条评论
为什么被折叠?



