当前位置:  开发笔记 > 编程语言 > 正文

如何从类中的方法动态创建模块级函数

如何解决《如何从类中的方法动态创建模块级函数》经验,为你挑选了1个好方法。

我试图从类中的方法动态创建模块级函数.因此,对于类中的每个方法,我想创建一个具有相同名称的函数,该函数创建类的实例,然后调用该方法.

我想这样做的原因是我可以采用面向对象的方法来创建Fabric文件.由于Fabric将调用模块级函数而不是类的方法,因此这是我的解决方法.

我使用以下链接让我开始

如何获取Python类中的方法列表?

动态添加函数到Python模块

如何在当前模块上调用setattr()?

http://effbot.org/zone/python-getattr.htm

在Python中使用函数名称从字符串调用模块的函数

如何在python中修改本地命名空间

我提出了以下代码

import inspect
import sys
import types

class TestClass(object):
    def __init__(self):
        pass

    def method1(self, arg1):
        print 'method 1 %s' % arg1

    def method2(self):
        print 'method 2'

def fabric_class_to_function_magic(module_name):
    # get the module as an object
    print module_name
    module_obj = sys.modules[module_name]
    print dir(module_obj)

    # Iterate over the methods of the class and dynamically create a function
    # for each method that calls the method and add it to the current module
    for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
        print
        print method
        method_name, method_obj = method

        # create a new template function which calls the method
        def newfunc_template(*args, **kwargs):
            tc = TestClass()
            func = getattr(tc, method_name)
            return func(*args, **kwargs)

        # create the actual function
        print 'code: ', newfunc_template.func_code
        print 'method_name: ', method_name
        newfunc = types.FunctionType(newfunc_template.func_code,
                                     {'TestClass': TestClass,
                                      'getattr': getattr,
                                      'method_name': method_name,
                                      },
                                     name=method_name,
                                     argdefs=newfunc_template.func_defaults,
                                     closure=newfunc_template.func_closure,
                                     )

        # add the new function to the current module
        setattr(module_obj, method_name, newfunc)

# test the dynamically created module level function
thismodule = sys.modules[__name__]
print dir(thismodule)
fabric_class_to_function_magic(__name__)
print dir(thismodule)
method1('arg1')
method2()

我收到以下错误

['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']
__main__
['TestClass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'sys', 'thismodule', 'types']

('__init__', )
code:  
method_name:  __init__

('method1', )
code:  
method_name:  method1

('method2', )
code:  
method_name:  method2
['TestClass', '__builtins__', '__doc__', '__file__', '__init__', '__name__', '__package__', 'fabric_class_to_function_magic', 'inspect', 'method1', 'method2', 'sys', 'thismodule', 'types']
Traceback (most recent call last):
  File "test.py", line 111, in 
    method1('arg1')
  File "test.py", line 88, in newfunc_template
    return func(*args, **kwargs)
TypeError: method2() takes exactly 1 argument (2 given)

它似乎重用了函数的引用?有任何想法吗?

更新:这是Ned Batchelder修复的工作代码

def fabric_class_to_function_magic(module_name):
    # get the module as an object
    module_obj = sys.modules[module_name]

    # Iterate over the methods of the class and dynamically create a function
    # for each method that calls the method and add it to the current module
    for method in inspect.getmembers(TestClass, predicate=inspect.ismethod):
        method_name, method_obj = method

        # get the bound method
        tc = TestClass()
        func = getattr(tc, method_name)

        # add the function to the current module
        setattr(module_obj, method_name, func)

更新2:这是我关于这个主题的博客文章:http://www.saltycrane.com/blog/2010/09/class-based-fabric-scripts-metaprogramming-hack/



1> Ned Batcheld..:

你过分思考你的解决方案.改变结尾为fabric_class_to_function_magic:

    tc = TestClass()
    func = getattr(tc, method_name)

    # add the new function to the current module
    setattr(module_obj, method_name, func)

它工作正常.无需创建新的函数对象,您的对象上已经有getattr返回的函数对象.getattr返回的绑定方法是可调用的东西.只需将其分配给您的模块属性,就可以了.

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有