Python:使用Self并动态地向对象添加方法

时间:2010-09-22 16:32:15

标签: python self dynamic-method

这是我的想法:从一个简单的对象开始:

class dynamicObject(object):
    pass

并且能够动态添加预先写好的方法:

def someMethod(self):
    pass

所以我可以这样做:

someObject = dyncamicObject()
someObject._someMethod = someMethod
someObject._someMethod()

问题是,它要我指定_someMethod()的self部分,使它看起来像这样:

someObject._someMethod(someObject)

这似乎有点奇怪,因为当一个方法“附加”到一个对象时,它不是自我隐含的吗?

我是Python的新思维方式的新手,我正试图摆脱像C#这样的语言的相同思维过程,所以这里的想法是能够通过选择和选择哪种验证方法来创建验证对象想要添加它而不是制作某种对象层次结构。我认为Python的“自我”想法对我有利,因为我认为该对象会隐含地知道将自己发送到附加到它的方法中。

有一点需要注意,该方法没有以任何方式附加到对象(完全不同的文件),所以可能这是问题?也许通过自己定义方法,self实际上是有问题的方法,因此不能暗示为对象?

5 个答案:

答案 0 :(得分:6)

虽然下面我试图回答字面问题,但我认为 Muhammad Alkarouri's answer更好地解决了问题应该如何解决的问题。


将方法添加到类dynamicObject,而不是对象someObject

class dynamicObject(object):
    pass

def someMethod(self):
    print('Hi there!')

someObject=dynamicObject()
dynamicObject.someMethod=someMethod
someObject.someMethod()
# Hi there!

当您说someObject.someMethod=someMethod时,someObject.__dict__会获得键值对('someMethod',someMethod)

当您说dynamicObject.someMethod=someMethod时,someMethod已添加到dynamicObject的{​​{1}}。您需要在课程中定义__dict__ someMethod表示方法调用。有关这方面的更多信息,请参阅Raymond Hettinger的essay on descriptors - 毕竟,方法只不过是一个描述符! - 和Shalabh Chaturvedi的essay on attribute lookup


还有另一种方法:

someObject.someMethod

但由于您将import types someObject.someMethod=types.MethodType(someMethod,someObject,type(someObject)) 定义为'someMethod'中的关键字,这确实是令人厌恶的,因为它不是方法的正确位置。事实上,你根本没有获得类方法,只是一个curried函数。这不仅仅是技术性问题。 dynamicObject的子类将无法继承someObject.__dict__函数。

答案 1 :(得分:6)

要实现您想要的目标(通过选择和选择我想添加到其中的验证方法来创建验证对象),更好的方法是:

class DynamicObject(object):
    def __init__(self, verify_method = None):
        self.verifier = verify_method
    def verify(self):
        self.verifier(self)

def verify1(self):
    print "verify1"

def verify2(self):
    print "verify2"

obj1 = DynamicObject()
obj1.verifier = verify1

obj2 = DynamicObject(verify2)
#equivalent to
#obj2 = DynamicObject()
#obj2.verify = verify2

obj1.verify()
obj2.verify()

答案 2 :(得分:0)

为什么不使用setattr?我发现这种方式更明确。

class dynamicObject(object):
    pass

def method():
    print "Hi"

someObject = dynamicObject()
setattr(someObject,"method", method)
someObject.method()

答案 3 :(得分:0)

当方法非常简单时,有时需要编写常规函数并在之后添加它是很烦人的。在那种情况下,lambdas可以拯救:

    class Square:
        pass

    Square.getX = lambda self: self.x
    Square.getY = lambda self: self.y
    Square.calculateArea = lambda self: self.getX() * self.getY()

希望这有帮助。

答案 4 :(得分:0)

如果你只想包装另一个类,而不必处理为任何实例分配新方法,你可以将该方法作为该类的静态方法:

class wrapperClass(object):
    @staticmethod
    def foo():
        print("yay!")

obj = wrapperClass()
obj.foo()  // Yay!

然后,您可以为任何其他类提供具有多重继承的.foo方法。

class fooDict(dict, wrapperClass):
    """Normal dict with foo method"""

foo_dict = fooDict()
foo_dict.setdefault('A', 10)
print(foo_dict)   // {'A': 10}
foo_dict.foo()    // Yay!