有没有办法检查 __getattr__ 中传入的参数或以其他方式根据传入参数重定向调用?
一些背景: 我们有一个交易系统,我们根据交易账单所在的国家/地区划分流量。我们有一个存在于 2 个实例中的日志记录表,一个数据库将事务记录到欧盟,另一个记录到其他任何地方。我们还有一个测试库,用于管理和隐藏使用数据库的内部内容,粗略地说,每个表都由一个类表示。我有一个表示表的类,并且数据库会话管理器类对于该类的两个实例中的每一个实例都有两个成员。我想要做的是创建一个通用的“meta dao”类,它将接受对它的任意调用,检查参数,并根据输入参数之一,随后将调用分派到代表类实例的正确数据库实例。我最初考虑的是重载每个方法,但这既笨重又肮脏。
我正在考虑使用 __getattr__ 来覆盖方法查找,以便我可以根据 __getattr__ 收到的方法名称调用正确的实例,但从我的情况来看明白,我无法从 __getattr__
中检查
传入的方法参数,因此在这种情况下我无法从其中正确分派。有谁对我可以追求的不同方向有任何想法,或者有一种从 __getattr__ 内部“检查”参数(而不仅仅是方法名称)的方法?
[编辑] 这是我正在谈论的内容的通用版本:
class BarBase(object):
def __init__(self, x):
self.x = x
def do_bar(self, i):
return self.x * i
class FooBar(BarBase):
def __init__(self, x):
super(FooBar, self).__init__(x)
def do_foo(self, i):
return self.x + i
class MetaFoo(object):
def __init__(self, bar_manager):
self.foo_manager = bar_manager
#something here that will take an arbitrary methodname and args as
#long as args includes a value named i, inspect i, and call
#bar_manager.fooa.[methodname](args) if i < 10,
#and bar_manager.foob.[methodname](args) if i >= 10
class BarManager(object):
def __init__(self):
self.bar_list = {}
def __get_fooa(self):
if 'fooa' not in self.bar_list.keys():
self.bar_list['fooa'] = FooBar('a')
return self.bar_list['fooa']
fooa = property(__get_fooa)
def __get_foob(self):
if 'foob' not in self.bar_list.keys():
self.bar_list['foob'] = FooBar('b')
return self.bar_list['foob']
foob = property(__get_foob)
def __get_foo(self):
if 'foo' not in self.bar_list.keys():
self.bar_list['foo'] = MetaFoo(self)
return self.bar_list['foo']
Some background:
We have a system for transactions where we devide the flow based upon the country the transaction bills to. We have a logging table that exists in 2 instances, one DB logging transactions to the EU, the other to anywhere else. We also have a test library that manages and hides the guts of working with the DB where roughly speaking each table is represented by a class. I have a class that represents the table, and the db session manager class has two members for each of the two instances of the class. What I want to do is create a generic 'meta dao' class that will take any arbitrary call to it, inspect the args, and based upon one of the input arguments, subsequently dispatch the call to the correct db instance-representing class instance. I initially thought about just overloading every method, but that's clunky and dirty.
I was looking at using __getattr__
to override the method lookup so that I could then call down to the correct instance based upon the name of the method __getattr__
recieves, but from what I understand, I can't inspect
the incoming method arguments from within __getattr__
, so I can't properly dispatch from within it in this case. Does anyone have any ideas of a different direction I can pursue, or a way to 'inspect' the arguments, not just the method name, from within __getattr__
?
[edit] Here's a genericized version of what I'm talking about:
class BarBase(object):
def __init__(self, x):
self.x = x
def do_bar(self, i):
return self.x * i
class FooBar(BarBase):
def __init__(self, x):
super(FooBar, self).__init__(x)
def do_foo(self, i):
return self.x + i
class MetaFoo(object):
def __init__(self, bar_manager):
self.foo_manager = bar_manager
#something here that will take an arbitrary methodname and args as
#long as args includes a value named i, inspect i, and call
#bar_manager.fooa.[methodname](args) if i < 10,
#and bar_manager.foob.[methodname](args) if i >= 10
class BarManager(object):
def __init__(self):
self.bar_list = {}
def __get_fooa(self):
if 'fooa' not in self.bar_list.keys():
self.bar_list['fooa'] = FooBar('a')
return self.bar_list['fooa']
fooa = property(__get_fooa)
def __get_foob(self):
if 'foob' not in self.bar_list.keys():
self.bar_list['foob'] = FooBar('b')
return self.bar_list['foob']
foob = property(__get_foob)
def __get_foo(self):
if 'foo' not in self.bar_list.keys():
self.bar_list['foo'] = MetaFoo(self)
return self.bar_list['foo']
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
按照这些思路应该可以工作:
然后您将创建两个实例并将它们组合在代理对象中:
Somethings along these lines should work:
Then you would create the two instances and combine them in a proxy object:
Python 装饰器 是你的朋友。你可以做类似这样的
输出:
如果你有几个方法要重写,你可以单独应用装饰器,甚至可以将参数(例如差异阈值)传递给不同的方法,但如果想重写所有方法,你可以添加一个重载所有方法的元类给定类的,但在这种情况下,按照
sth
的建议覆盖__getattr__
是一个不错的选择python decorators are your friend. You can do something like this
output:
If you have few methods to override you can individually apply decorator and even can pass parameters e.g. diff threshold to different methods, but if want to override all methods may be you can add a metaclass which overloads all method of given class, but in this case overriding
__getattr__
as suggested bysth
is a good alternative基于传递的参数进行调度是一个两步过程:
__getattr__
返回一个代理方法下面是一个示例:
运行时,给出:
后面是
:要使这项工作有效,您要么必须始终使用相同的关键字参数(并在调用函数时命名它),要么始终将参数放在相同的位置。或者您可以为每种样式/类别/任何类型的方法创建多个不同的代理。
Dispatching based on passed arguments is a two-step process:
__getattr__
returns a proxy methodHere's an example:
When run, this gives:
Followed by:
To make this work you would either have to always use the same keyword argument (and name it when you call the function) or always have the argument in the same position. Or you can make several different proxies for each style/category/whatever type of method.