如何为一个对象的所有方法起别名?
How to alias all methods from an object?
我正在创建一个脚本,它实际上是供其他用户编写代码的环境。
我在 class 中声明了几个方法并实例化了一个对象,这样用户就可以将这些方法用作简单的解释器函数,如下所示:
from code import interact
class framework:
def method1(self, arg1):
# code for method1
def method2(self, arg2):
# code for method2
def main():
fw = framework()
# Aliases
method1 = fw.method1
method2 = fw.method2
interact(local=locals())
因为我不希望用户使用 fw.method1(arg)
调用方法,所以我设置了别名。问题是,由于框架 class 正在开发中,我必须不断用我创建的方法的新别名更新主脚本。
是否有一种简单的方法可以去掉调用中的“fw.
”部分,并让 class 框架下的所有方法在 main 下自动可见?
我不知道你打算用这些函数做什么,但如果它们不是 static
它就不可能在 class 之外工作:
fs = [func for func in dir(c) if callable(getattr(c, func)) and not func.startswith("__")]
for func in fs:
globals()[func] = getattr(c, func)
这会将 class c
中的所有自定义函数放入全局范围。
你基本上想做两件事:
- 获取class实例的方法列表
- 将函数动态添加到本地作用域
前者可以通过标准库中的inspect
模块实现,后者可以使用vars
.
尝试以下操作:
import inspect
from code import interact
class framework:
def method1(self, arg1):
# code for method1
def method2(self, arg2):
# code for method2
def main():
fw = framework()
# get the methods of fw and update vars().
# getmembers returns a list of two-tuples with (<Name>, <function>)
methods = inspect.getmembers(fw, predicate=inspect.ismethod)
vars().update({method[0]: method[1] for method in methods})
interact(local=locals())
你控制传递给 interact
的字典,所以把你想要的放进去,不用担心 main
中的局部变量:
d={}
for n in vars(framework):
if n.startswith('_'): continue # probably
x=getattr(fw,n)
if callable(x): d[n]=x
interact(local=d)
这适用于常规、静态和 class 方法。它看不到实例属性(除非它们隐藏了 class 属性)或继承的方法。
前者仅在实例将函数存储为属性时才重要(在这种情况下,您可能希望也可能不希望它们可用)。后者很方便,因为它省略了 object
;如果还有其他基数 class,则可以通过搜索 framework.__mro__
(并且仍然省略 object
)轻松包含它们。
这里有一些类似于@Davis Herring 的回答,经过充实和重新包装:
#from code import interact
def interact(local):
local['method1'](42)
local['method2']('foobar')
class Framework:
def method1(self, arg1):
print('Framework.method1({!r}) called'.format(arg1))
def method2(self, arg2):
print('Framework.method2({!r}) called'.format(arg2))
def get_callables(obj):
return {name: getattr(obj, name) for name in vars(obj.__class__)
if callable(getattr(obj, name))}
def main():
fw = Framework()
# # Aliases
# method1 = fw.method1
# method2 = fw.method2
interact(local=get_callables(fw))
if __name__ == '__main__':
main()
输出:
Framework.method1(42) called
Framework.method2('foobar') called
我正在创建一个脚本,它实际上是供其他用户编写代码的环境。
我在 class 中声明了几个方法并实例化了一个对象,这样用户就可以将这些方法用作简单的解释器函数,如下所示:
from code import interact
class framework:
def method1(self, arg1):
# code for method1
def method2(self, arg2):
# code for method2
def main():
fw = framework()
# Aliases
method1 = fw.method1
method2 = fw.method2
interact(local=locals())
因为我不希望用户使用 fw.method1(arg)
调用方法,所以我设置了别名。问题是,由于框架 class 正在开发中,我必须不断用我创建的方法的新别名更新主脚本。
是否有一种简单的方法可以去掉调用中的“fw.
”部分,并让 class 框架下的所有方法在 main 下自动可见?
我不知道你打算用这些函数做什么,但如果它们不是 static
它就不可能在 class 之外工作:
fs = [func for func in dir(c) if callable(getattr(c, func)) and not func.startswith("__")]
for func in fs:
globals()[func] = getattr(c, func)
这会将 class c
中的所有自定义函数放入全局范围。
你基本上想做两件事:
- 获取class实例的方法列表
- 将函数动态添加到本地作用域
前者可以通过标准库中的inspect
模块实现,后者可以使用vars
.
尝试以下操作:
import inspect
from code import interact
class framework:
def method1(self, arg1):
# code for method1
def method2(self, arg2):
# code for method2
def main():
fw = framework()
# get the methods of fw and update vars().
# getmembers returns a list of two-tuples with (<Name>, <function>)
methods = inspect.getmembers(fw, predicate=inspect.ismethod)
vars().update({method[0]: method[1] for method in methods})
interact(local=locals())
你控制传递给 interact
的字典,所以把你想要的放进去,不用担心 main
中的局部变量:
d={}
for n in vars(framework):
if n.startswith('_'): continue # probably
x=getattr(fw,n)
if callable(x): d[n]=x
interact(local=d)
这适用于常规、静态和 class 方法。它看不到实例属性(除非它们隐藏了 class 属性)或继承的方法。
前者仅在实例将函数存储为属性时才重要(在这种情况下,您可能希望也可能不希望它们可用)。后者很方便,因为它省略了 object
;如果还有其他基数 class,则可以通过搜索 framework.__mro__
(并且仍然省略 object
)轻松包含它们。
这里有一些类似于@Davis Herring 的回答,经过充实和重新包装:
#from code import interact
def interact(local):
local['method1'](42)
local['method2']('foobar')
class Framework:
def method1(self, arg1):
print('Framework.method1({!r}) called'.format(arg1))
def method2(self, arg2):
print('Framework.method2({!r}) called'.format(arg2))
def get_callables(obj):
return {name: getattr(obj, name) for name in vars(obj.__class__)
if callable(getattr(obj, name))}
def main():
fw = Framework()
# # Aliases
# method1 = fw.method1
# method2 = fw.method2
interact(local=get_callables(fw))
if __name__ == '__main__':
main()
输出:
Framework.method1(42) called
Framework.method2('foobar') called