python - 在 Python 3+ 中以编程方式向类添加方法
问题描述
我有一个为 API 提供简单接口的类。我想为每个路由在该类上定义一个方法。
由于大多数路由是相同的,因此可以将许多功能分解为更通用的函数,许多路由只是该函数的部分应用版本
class MyAPIWrapper:
def _get_results(self, route, **params):
# Do the important stuff here
results = ...
return results
def get_customers(self):
return self._get_results(self, 'customers')
def get_transactions(self):
return self._get_results(self, 'transactions')
# etc, etc, etc
但是,很明显,这仍然会导致类定义中出现大量样板。
一种替代方法是添加一个新方法,以编程方式添加每个路由的方法:
import functools
class MyAPIWrapper:
def __init__(self):
self._init_route_methods()
def _get_results(self, route, **params):
# Do the important stuff here
results = ...
return results
def _init_route_methods(self):
for route in ['customers', 'transactions', ...]:
route_fn = functools.partial(self. _get_results, route)
setattr(self, f'get_{route}', route_fn)
这样做的好处是减少了样板代码的数量,并且可以轻松添加/删除路由。但是,在初始化时添加方法对我来说有点不雅。
有没有更好和/或更惯用的方法来做到这一点?
解决方案
您可能会惊讶于这会成功:
class MyAPIWrapper:
def _get_results(self, route, **params):
# Do the important stuff here
return route
for route in ['customers', 'transactions']:
exec("""
def get_{0}(self):
return self._get_results('{0}')
""".strip().format(route))
MyAPIWrapper().get_customers() # return customers
MyAPIWrapper().get_transactions() # return transactions
优点
- 良好的可读性
- 最少的代码更改
缺点
请注意,这exec
比 有一点开销setattr(MyAPIWrapper,'get_%s'%route, ...)
,这仅在您要在循环中创建数百万个方法时才重要。
如果您想对许多不同的 APIWrapper 类执行相同的操作,请考虑改用类装饰器。
推荐阅读
- javascript - 映射对象的对象并推送非重复
- python - 如何制作两个不相互交互的独立下拉列表?
- python - 如何修复错误自动化游戏 Python 代码
- c# - C# 多次调用不同类型的泛型方法
- react-native - 如何在 React Native 中跟踪智能手机的 GPS 位置
- vue.js - 嵌入 youtube 视频的内容安全策略 nuxtjs
- python - Pandas - 为每个单元格重复一个字符串,每个单元格返回一个字母
- javascript - React ContextMenu 和 Draggable
- python - Dash Web 应用程序不起作用。错误:POST /_dash-update-component HTTP/1.1" 500 -
- cordova - cordova-res 返回错误:pngload_buffer:不可恢复状态