gpt4 book ai didi

python - 定义或记录 __getattr__ 处理的调用的正确方法是什么?

转载 作者:太空宇宙 更新时间:2023-11-03 16:57:46 25 4
gpt4 key购买 nike

我有一个类,其工作是包装另一个类(我不控制的代码),拦截对包装类的所有调用,执行一些逻辑,并将调用传递给底层类。这是一个例子:

class GithubRepository(object):

def get_commit(self, sha):
return 'Commit {}'.format(sha)

def get_contributors(self):
return ['bobbytables']


class LoggingGithubRepositoryWrapper(object):

def __init__(self, github_repository):
self._github_repository = github_repository

def __getattr__(self, name):
base_func = getattr(self._github_repository, name)

def log_wrap(*args, **kwargs):
print "Calling {}".format(name)
return base_func(*args, **kwargs)

return log_wrap

if __name__ == '__main__':

git_client = LoggingGithubRepositoryWrapper(GithubRepository())

print git_client.get_commit('abcdef1245')
print git_client.get_contributors()

如您所见,我执行此操作的方法是实现 __getattr__在包装类上并委托(delegate)给底层类。这种方法的缺点是 LoggingGithubRepositoryWrapper 的用户不知道底层有哪些属性/方法GithubRepository实际上有。

这引出了我的问题:有没有办法定义或记录 __getattr__ 处理的调用? 理想情况下,我希望能够自动完成 git_client.并提供支持方法的列表。提前感谢您的帮助!

最佳答案

您可以通过几种不同的方式来完成此操作,但它们不会涉及使用 __getattr__

您真正需要做的是动态创建您的类,或者至少动态创建您的类上的包装函数。在 python 中,有几种方法可以做到这一点。

您可以使用 type() 或元类构建类定义,或者使用 __new__ 方法在类实例化上构建它。

每次调用 LoggingGithubRepositoryWrapper() 时,都会调用 __new__ 方法。在这里,它查看 github_repository 参数上的所有属性并查找所有非私有(private)方法。然后,它在实例化的 LoggingGithubRepositoryWrapper 类实例上创建一个函数,将存储库调用包装在日志记录语句中。

最后,它传回修改后的类实例。然后调用__init__

from types import MethodType


class LoggingGithubRepositoryWrapper(object):

def __new__(cls, github_repository):
self = super(LoggingGithubRepositoryWrapper, cls).__new__(cls)
for name in dir(github_repository):
if name.startswith('__'):
continue
func = getattr(github_repository, name)
if isinstance(func, MethodType):
setattr(self, name, cls.log_wrap(func))
return self

@staticmethod
def log_wrap(func):
def wrap(*args, **kwargs):
print 'Calling {0}'.format(func.__name__)
return func(*args, **kwargs)
return wrap

def __init__(self, github_repository):
... # this is all the same

关于python - 定义或记录 __getattr__ 处理的调用的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35278210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com