Python中如何实现函数依赖的功能可扩展?
想实现的目标是,主函数 f_a(), 是个解析帧的函数,当前把不同帧格式的解析函数都写死在了主函数里。当然也可以做成 list 当参数传入。但使用这个函数就很奇怪,每次都要传这个 list,感觉这个接口不好。
想问下有什么好的代码结构,可以解决这个问题。最好是能库函数和用户函数分离的结构。
Python中如何实现函数依赖的功能可扩展?
3 回复
在Python里搞函数依赖扩展,我一般用装饰器配合注册表模式。直接上代码:
from functools import wraps
from typing import Dict, Callable, Any
class DependencyRegistry:
def __init__(self):
self._dependencies: Dict[str, Callable] = {}
self._instances: Dict[str, Any] = {}
def register(self, name: str):
def decorator(func):
self._dependencies[name] = func
@wraps(func)
def wrapper(*args, **kwargs):
if name not in self._instances:
self._instances[name] = func(*args, **kwargs)
return self._instances[name]
return wrapper
return decorator
def get(self, name: str):
if name not in self._instances:
if name in self._dependencies:
self._instances[name] = self._dependencies[name]()
else:
raise KeyError(f"Dependency '{name}' not registered")
return self._instances[name]
# 全局注册表实例
registry = DependencyRegistry()
# 使用示例
@registry.register("database")
def create_db_connection():
print("Creating database connection...")
return {"db": "postgresql://localhost/mydb"}
@registry.register("cache")
def create_cache_client():
print("Creating cache client...")
return {"cache": "redis://localhost"}
@registry.register("service")
def create_service():
# 依赖注入:获取已注册的依赖
db = registry.get("database")
cache = registry.get("cache")
print(f"Creating service with db={db}, cache={cache}")
return {"service": "main_service", "deps": [db, cache]}
# 测试
if __name__ == "__main__":
# 获取service时会自动创建其依赖
service = registry.get("service")
print(f"Service: {service}")
# 再次获取会使用缓存实例
service2 = registry.get("service")
print(f"Same instance: {service is service2}")
这个实现的核心思路是:
DependencyRegistry类管理所有依赖的注册和实例化@registry.register()装饰器用来声明依赖项registry.get()方法获取依赖时,如果还没实例化就创建,实现了懒加载- 依赖之间可以相互引用,
create_service函数里通过registry.get()获取它需要的database和cache
这样扩展起来很方便,要加新依赖就再加个@registry.register装饰的函数。依赖关系在函数内部通过registry.get()显式声明,比隐式导入更清晰。
用装饰器注册依赖项,用的时候直接get就行。
方式很多:<br>class X:<br> def __init__(参数):<br> pass<br><br>def f_a(x):<br> if isinstance(x, X):<br> pass<br> else:<br> raise XXXXError('参数类型不对')<br>f_a(X(xx,yy,zzz))<br><br>def f_a(*args):<br> pass<br><br>f_a(*a_list)<br><br><br>def f_a(**kwargs):<br> pass<br><br>f_a(x=xx,y=yy)<br><br>
说实话没看懂你的需求是啥

