Python在运行时添加方法

Ale*_*rry 0 python methods class class-method

我正在尝试在运行时动态地向类添加方法,并且看到一些问题:

#Here we define a set of symbols within an exec statement and put them into the dictionary d
d = {}
exec "def get_%s(self): return self.%s" % (attr_name, attr) in d

#Now, we bind the get method stored in d['get_%s'] to our object (class)
func = d['get_%s' % (attr_name)].__get__(d['get_%s' % (attr_name)], class)
setattr(class_instance, func.__name__, func)
Run Code Online (Sandbox Code Playgroud)

当我尝试调用生成的get方法时,我看到如下:

Traceback (most recent call last):
  File "Textere_AdvancedExample.py", line 77, in <module>
    count = fact.get_counter()
  File "<string>", line 1, in get_counter
AttributeError: 'function' object has no attribute '_counter'
Run Code Online (Sandbox Code Playgroud)

编辑

基于迄今为止给出的一些特殊回答,我想我需要澄清为什么我这样做.

我正在尝试构建一个类似下面示例的注释:

@getters
@singleton
class A() {

    def __init__(self):
        self._a = "a"
        self._b = "b"
 }
Run Code Online (Sandbox Code Playgroud)

根据类中的名称,注释将在运行时为私有类变量构建getter,并将它们绑定到singleton实例.

我采取的策略是使用一组带有一组dicts的Application Context类.然后,将上下文传递给注释,该注释将实例和类添加到这些dicts中.

在启动时,应用程序上下文负责读取字典,然后构建并将get方法绑定到相应的单例对象.

EDIT2

所以这个开发是在与我的朋友们进行了一些讨论之后开始的,他们是Java开发人员,特别是两个库:Spring&Lombok

我想看看这些特定的功能是否可以在Python中实现.因此,应用程序上下文最初来自尝试获得类似于Spring的autowire注释的功能.我没有问题就这样做了.

然后,我得到了生成getter和setter,并意识到我将从Java实现中获得Python的根本区别:Lombok在编译时执行此操作而Python未编译.这意味着我必须根据被注释的内容动态生成方法,并在运行时手动将它们绑定到对象.因此,您会看到Java实现的这种扭曲.

对于那些感兴趣的人,可以在这里找到完整的代码

Ser*_*sta 6

您可以轻松地动态添加静态方法或类方法:

class A:
    pass

@staticmethod
def foo0(x):
    return x * 2

a = A()
A.foo = foo0
a.foo(3)
Run Code Online (Sandbox Code Playgroud)

返回 6

class A:
    val = 3

@classmethod
def foo0(cls, x):
    return x * cls.val

a = A()
A.foo = foo0
a.foo(2)
Run Code Online (Sandbox Code Playgroud)

返回 6

您还可以将特定方法添加到类的实例(几乎相同的方式)

class A:
    pass

a = A()
a.foo = (lambda x: 2*x)
a.foo(3)
Run Code Online (Sandbox Code Playgroud)

回报 6

您还可以通过使用types模块将实例方法添加到类中(事实上​​,这种通用方法也可用于创建静态和类方法,以及仅实例方法):

class A:
    def __init__(self, val):
        self.val = val


a = A(3)
A.foo = types.MethodType((lambda self, x: self.val * x), None, A)
a.foo(2)
Run Code Online (Sandbox Code Playgroud)

回报 6

但这实际上是猴子修补,这是一个快速而肮脏的黑客攻击,只有当你需要传递稍微更改的类并且不允许更改名称时才应该使用它.向类中添加功能的漂亮而干净的方法是继承


为了使这个答案更好,上面的内容适用于Python 2.

对于Python 3,只能使用创建类和静态方法的第一种方法,因为types模块丢失了许多类型.

并创建一个实例方法,如下所示:

class A:
    def __init__(self, val):
        self.val = val


a = A(3)
A.foo = (lambda self, x: self.val * x)
a.foo(2)
Run Code Online (Sandbox Code Playgroud)

回报6.这里不需要特殊的构造