Python:使用self动态为对象添加方法
这是我的想法:先从一个简单的对象开始:
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 个回答
有时候,写一个普通的函数会让人觉得麻烦,尤其是当这个方法非常简单的时候。在这种情况下,使用“lambda”表达式就能派上用场了:
class Square:
pass
Square.getX = lambda self: self.x
Square.getY = lambda self: self.y
Square.calculateArea = lambda self: self.getX() * self.getY()
希望这对你有帮助。
为了实现你想要的效果(创建一个对象,用来选择性地添加我想要的验证方法),有一个更好的方法是:
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()
虽然我下面尝试回答了字面上的问题,但我觉得 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
函数。