如何为一个对象的所有方法起别名?

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 中的所有自定义函数放入全局范围。

你基本上想做两件事:

  1. 获取class实例的方法列表
  2. 将函数动态添加到本地作用域

前者可以通过标准库中的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