想知道在运行时是否可以更改方法的功能,例如
x = obj1 + obj2
return x+y
并且您想要添加
x = obj1 + obj2
x+= obj3
return x+y
想知道在运行时是否可以更改方法的功能,例如
x = obj1 + obj2
return x+y
并且您想要添加
x = obj1 + obj2
x+= obj3
return x+y
class Dog:
def talk(self):
print "bark"
dog1 = Dog()
dog1.talk() # --> Bark
def cat_talk(self):
print "Meow"
Dog.talk = cat_talk
dog1.talk() # --> Meow
但是你不想做这样的事情,否则谁维护或调试这个程序肯定会想杀了你(而且这个人可能就是你自己)
注意:特殊的“dunder”方法的每个实例的定制不起作用(由于内部Python优化)。解决方法是使特殊方法调用常规方法,然后在常规方法上进行每个实例的定制。有关详细信息,请参见为什么动态添加`__call__`方法到实例不起作用?。
一切皆有可能,您可以在运行时进行堆栈操作并插入字节码。参见类似byteplay
的工具。
这种修改方式不直观且难以阅读,最好的方法是一开始就将x += obj3
留在那里,并将obj3
设置为0
; 当您需要该行执行某些操作时,使用obj3
上的非零值即可...
主要用短语"Monkey Patching"(其他人也提到过)来描述,或者当通常谈论代码操作和/或运行时执行时,通常也用"dynamic/runtime code execution"这个短语来表示[...]
在Python中,您可以按照以下或以下简单的方式进行操作:
currentCode = '''
global x
x = objs[0] + objs[1]
'''
newCode = '''
global x
x = objs[0] + objs[1]
x += objs[2]
x += y
'''
class Ego:
def doMethod(self, objs=None,y=1):
exec(currentCode)
return x
def main():
I = Ego()
obj1 = 8
obj2 = 2
obj3 = 1
print('Before:', I.doMethod([obj1,obj2]))
global currentCode
currentCode = newCode #Swiching to new-Code
print('After :', I.doMethod([obj1,obj2,obj3]))
if __name__ == "__main__":
main()
输出结果为:
Before: 10
After : 12
⚠️ 免责声明:这不是一条建议(至少不适用于所有情况),这只是一种方法,一个概念证明,因为它确实是有效的(所以请不要因此讨厌我。)
程序经常在运行时更改方法的功能,这被称为“泛化”。
你所要做的就是编写一个更通用的算法。这并不难。
def run_time_change( y, *object_list ):
x=sum( object_list )
return x+y
example1 = run_time_change(y, obj1, obj2 )
example2 = run_time_change(y, obj1, obj2, obj3 )
没有“运行时”代码更改的地方。这是错误的。
正确的做法是编写更通用的算法。
你想做什么并不完全清楚,但是在运行时更改方法和类被称为“ Monkey Patching”, 这在 Python 中不受欢迎(正如名称所示)。
原因是因为这让你的代码极难调试,因为通过阅读代码很难确定调用哪个版本的方法。或者更有可能的是,执行调试的人甚至没有意识到方法已经被更改了,所以他们看到的行为根本无法理解。
因此,虽然可以动态更改方法,但最好不要这样做。如果您提供有关您尝试解决的问题的更多详细信息,其他人将能够建议更“Pythonic”的解决方案。
y
是什么?Y
是什么?你说的return x=Y
是什么意思? - Andrew Jaffe