Python:使用self动态为对象添加方法

3 投票
5 回答
4827 浏览
提问于 2025-04-16 04:27

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

class dynamicObject(object):
    pass

然后能够动态地给它添加一些预先写好的方法:

def someMethod(self):
    pass

这样我就可以这样做:

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

问题是,它让我在 _someMethod() 中指定 self 部分,所以看起来像这样:

someObject._someMethod(someObject)

这让我觉得有点奇怪,因为当一个方法“附加”到一个对象上时,self 不应该是隐含的吗?

我刚接触 Python 的思维方式,想要摆脱像 C# 这样的语言中的思维模式。所以我的想法是,能够创建一个用于验证的对象,通过选择我想添加的验证方法,而不是构建某种对象层级。我原以为 Python 的“self”概念会对我有利,因为我认为对象会自动知道把自己传递给附加的方法。

需要注意的一点是,这个方法并没有以任何方式附加到对象上(完全是不同的文件),所以这可能是问题所在?也许通过单独定义这个方法,self 实际上是指这个方法本身,因此不能被隐含为对象?

5 个回答

0

有时候,写一个普通的函数会让人觉得麻烦,尤其是当这个方法非常简单的时候。在这种情况下,使用“lambda”表达式就能派上用场了:

    class Square:
        pass

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

希望这对你有帮助。

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()
7

虽然我下面尝试回答了字面上的问题,但我觉得 Muhammad Alkarouri的回答更好地解决了这个问题的实际解决方法。


应该把方法添加到类 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__dict__ 中。你需要在类中定义 someMethod,这样 someObject.someMethod 才能像调用方法一样工作。想了解更多,可以看看Raymond Hettinger的关于描述符的文章——毕竟,方法不过是描述符罢了!——还有Shalabh Chaturvedi的关于属性查找的文章


还有另一种方法:

import types
someObject.someMethod=types.MethodType(someMethod,someObject,type(someObject))

但这实际上是个大问题,因为你把 'someMethod' 定义为 someObject.__dict__ 中的一个键,这不是定义方法的正确地方。实际上,你根本得不到一个类方法,只是一个柯里化的函数。这不仅仅是个技术细节,dynamicObject 的子类将无法继承 someMethod 函数。

撰写回答