在 class 上调用任意方法,例如 xmlrpclib.ServerProxy
Call arbitrary methods on class like xmlrpclib.ServerProxy
我有一个远程 api 只接受 XML,可能被称为
api = xmlrpclib.ServerProxy(IP)
result = api.Execute({"Method": 'Method_name', "Params": [P1, P2],
... # technical values - authentication, etc
})
技术值不会经常更改 - 整个脚本通常会为它们使用相同的值,所以我创建了一个 class 有一个方法
def call(self, method_name, params):
self.api.Execute(<constructed dictionary>)
我想知道是否可以像 self.api
的方法一样直接调用这些方法,例如:
self.api.method_name(params)
这将依次填写 .Execute
和我的其余部分,总体思路如下:
def __getattr__(self, item):
if item in self.__dict__:
return self.item
else:
return functools.partial(self.call, method_name=item)
因此,如果我在 class(self.foo
、self.bar
等)中定义了一个方法 - 调用它会产生 self.foo
和 self.bar
。
像 self.api.METHOD(params)
一样调用它,其中 METHOD
是一个自定义方法,但是这种方法 "pollutes" 我没有定义的其他方法,比如 self.api.__repr__
和喜欢
根据this question,我覆盖__getitem__
的方法是否完全不正确?如果是这样 - 我应该如何实施?
我最近看了 a talk by Raymond Hettinger,这个 post 让我想起了它,所以我想我会 link。我认为这为您在 post:
中描述的方法提供了很好的论据
让 API 为您服务
首先,我认为压倒 __getattr__
并不像 post 你相信的那样有罪。
class MyAPI(object):
base_args = {'token': 'foobarauthtoekn'}
def __init__(self, ip):
self._api = ServerProxy(ip)
def _execute(self, method='', **kwargs):
argdict = {'Method': method}
argdict.update(MyAPI2.base_args)
argdict.update(kwargs)
self._api.Execute(argdict)
def __getattr__(self, attr):
return self.__dict__.get(
attr, partial(self._execute, method=attr))
api = MyAPI('127.0.0.1')
# Execute({'token': ..., 'Method': 'get_users', 'arg1': 'foo' ...}) =
api.get_users(arg1='foo', arg2='bar')
# Execute({'token': ..., 'Method': 'get_data', 'foo': 'stuff' ...}) =
api.get_data(foo='stuff', bar='zxcv')
我喜欢这个,因为它的代码不多,它让我们以更方便的方式使用 Execute
(使用关键字参数),而不依赖于内部 API 的支持].
通过元类的特殊行为
另一种方法使我们不必重写 __getattr__
以防我低估了它的错误程度,并且它也可以被认为更 pythonic,因为我们明确列举了我们将通过 API 包装器提供的方法:
class APIMeta(type):
def __new__(cls, clsname, bases, attrs):
def exec_generic(name):
base_args = {'token': 'foobarauthtoekn'}
def exec_wrapper(self, params):
args = {'Method': name}
args.update(base_args)
args.update(params)
return self._api.Execute(args)
return exec_wrapper
new_attrs = {
name: val if name.startswith('__') else exec_generic(name)
for name, val in attrs.items() }
return super(APIMeta, cls).__new__(cls, clsname, bases, new_attrs)
class MyAPI(object, metaclass=APIMeta):
def __init__(self, ip):
self._api = ServerProxy(ip)
def get_users(self):
pass
def get_data(self):
pass
# ...
实际上,我不喜欢这样,因为它只不过是一种 非常 令人费解的写作方式:
class MyAPI(object):
_base_args = {'token': 'foobarauthtoken'}
def __init__(self, ip):
self._api = ServerProxy(ip)
def get_users(self, params):
argdict = {'Method': 'get_users'}
argdict.update(MyAPI._base_args)
argdict.update(params)
return self._api.Execute(argdict)
# ...
如果你有很多方法,它将为你节省大量的输入,如果你想深入了解元编程或加深你对 python 语言.
Here's 两者的演示。
我有一个远程 api 只接受 XML,可能被称为
api = xmlrpclib.ServerProxy(IP)
result = api.Execute({"Method": 'Method_name', "Params": [P1, P2],
... # technical values - authentication, etc
})
技术值不会经常更改 - 整个脚本通常会为它们使用相同的值,所以我创建了一个 class 有一个方法
def call(self, method_name, params):
self.api.Execute(<constructed dictionary>)
我想知道是否可以像 self.api
的方法一样直接调用这些方法,例如:
self.api.method_name(params)
这将依次填写 .Execute
和我的其余部分,总体思路如下:
def __getattr__(self, item):
if item in self.__dict__:
return self.item
else:
return functools.partial(self.call, method_name=item)
因此,如果我在 class(self.foo
、self.bar
等)中定义了一个方法 - 调用它会产生 self.foo
和 self.bar
。
像 self.api.METHOD(params)
一样调用它,其中 METHOD
是一个自定义方法,但是这种方法 "pollutes" 我没有定义的其他方法,比如 self.api.__repr__
和喜欢
根据this question,我覆盖__getitem__
的方法是否完全不正确?如果是这样 - 我应该如何实施?
我最近看了 a talk by Raymond Hettinger,这个 post 让我想起了它,所以我想我会 link。我认为这为您在 post:
中描述的方法提供了很好的论据让 API 为您服务
首先,我认为压倒 __getattr__
并不像 post 你相信的那样有罪。
class MyAPI(object):
base_args = {'token': 'foobarauthtoekn'}
def __init__(self, ip):
self._api = ServerProxy(ip)
def _execute(self, method='', **kwargs):
argdict = {'Method': method}
argdict.update(MyAPI2.base_args)
argdict.update(kwargs)
self._api.Execute(argdict)
def __getattr__(self, attr):
return self.__dict__.get(
attr, partial(self._execute, method=attr))
api = MyAPI('127.0.0.1')
# Execute({'token': ..., 'Method': 'get_users', 'arg1': 'foo' ...}) =
api.get_users(arg1='foo', arg2='bar')
# Execute({'token': ..., 'Method': 'get_data', 'foo': 'stuff' ...}) =
api.get_data(foo='stuff', bar='zxcv')
我喜欢这个,因为它的代码不多,它让我们以更方便的方式使用 Execute
(使用关键字参数),而不依赖于内部 API 的支持].
通过元类的特殊行为
另一种方法使我们不必重写 __getattr__
以防我低估了它的错误程度,并且它也可以被认为更 pythonic,因为我们明确列举了我们将通过 API 包装器提供的方法:
class APIMeta(type):
def __new__(cls, clsname, bases, attrs):
def exec_generic(name):
base_args = {'token': 'foobarauthtoekn'}
def exec_wrapper(self, params):
args = {'Method': name}
args.update(base_args)
args.update(params)
return self._api.Execute(args)
return exec_wrapper
new_attrs = {
name: val if name.startswith('__') else exec_generic(name)
for name, val in attrs.items() }
return super(APIMeta, cls).__new__(cls, clsname, bases, new_attrs)
class MyAPI(object, metaclass=APIMeta):
def __init__(self, ip):
self._api = ServerProxy(ip)
def get_users(self):
pass
def get_data(self):
pass
# ...
实际上,我不喜欢这样,因为它只不过是一种 非常 令人费解的写作方式:
class MyAPI(object):
_base_args = {'token': 'foobarauthtoken'}
def __init__(self, ip):
self._api = ServerProxy(ip)
def get_users(self, params):
argdict = {'Method': 'get_users'}
argdict.update(MyAPI._base_args)
argdict.update(params)
return self._api.Execute(argdict)
# ...
如果你有很多方法,它将为你节省大量的输入,如果你想深入了解元编程或加深你对 python 语言.
Here's 两者的演示。