动态定义类中的方法

时间:2017-03-22 10:10:08

标签: python python-3.x

我尝试根据对象创建过程中给出的参数动态定义类中的函数。我尝试了一些想法(下面的代码),但它们都无效。也许这是不可能的。我想这样做是因为我会在蒙特卡罗模拟中经常调用_exec方法。

我的第一个失败的想法:

class Test_Class_1():
def __init__(self, a = None):
    if a:
        self.a = a

if hasattr(self, 'a'):    #self is undefined.
    def _exec(self):
        print(self.a)
else:
    def _exec():
        print('no a')

我的第二个失败的想法:

class Test_Class_2():
def __init__(self, a = None):
    if a:
        self.a = a

try self.a:           #this is invalid syntax
    def _exec(self):
        print(self.a)
except:
    def _exec():
        print('no a')

我当然可以创建不同的类来实现这一点,但我更希望一个类具有更易于理解的代码结构(更短)。

感谢您的想法!

3 个答案:

答案 0 :(得分:2)

您可以覆盖__setattr__()方法,根据属性_exec()的值动态更新a方法。 _exec()的两个不同实现作为类中的方法提供,并且每当修改属性时都会选择适当的实现。

如果使用__delattr__删除属性,也会覆盖del

class TestClass:
    def __init__(self, a=None):
        self.a = a

    def _exec_a(self):
        print(self.a)

    def _exec_no_a(self):
        print('no a')

    def __setattr__(self, name, value):
#        print('__setattr__():', name, value)
        super().__setattr__(name, value)
        if name == 'a':
            if value is not None:
                self._exec = self._exec_a
            else:
                del self.a

    def __delattr__(self, name):
#        print('__delattr__():', name)
        super().__delattr__(name)
        if name == 'a':
            self._exec = self._exec_no_a

像这样使用:

>>> x = TestClass()
>>> x.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'TestClass' object has no attribute 'a'

>>> x._exec()
no a
>>> x.a = 123
>>> x._exec()
123
>>> x.a = 'hello'
>>> x._exec()
hello

>>> x.a = None
>>> x.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'TestClass' object has no attribute 'a'
>>> x._exec()
no a
>>> x.a = 500
>>> x._exec()
500
>>> del x.a
>>> x._exec()
no a
>>> x.a = True
>>> x._exec()
True

>>> x = TestClass(a='xyz')
>>> x._exec()
xyz
>>> del x.a
>>> x._exec()
no a

答案 1 :(得分:1)

这样做的一种自然方式是:

class Test_Class_1():
    def __init__ (self, a=None):
        if a:
            self.my_func = lambda y: y*y

m = Test_Class_1()
m.my_func(100) # raises an error because my_func doesn't exist
v = Test_Class_1(100)
v.my_func(100) # returns 10000

您的第一个想法不起作用,因为self是一个局部变量,仅在执行方法时存在。在执行类主体时,它不存在。

答案 2 :(得分:0)

可以这样做,只需创建一个辅助函数,使用setattr设置函数:

def set_func(self):
    if hasattr(self, 'a'):    #self is undefined.
        def _exec(self):
            print(self.a)
        setattr(type(self), '_exec', _exec)
    else:
        @staticmethod
        def _exec():
            print('no a')
        setattr(type(self), '_exec', _exec)

并在a中设置__init__后调用它:

 def __init__(self, a = None):
    if a:
        self.a = a
    self.set_func()