9

Wondering if its is possible to change functionalify of a method during runtime e.g

x = obj1 + obj2
return x+y

and you want to add

x = obj1 + obj2
x+= obj3
return x+y
Simone
  • 11,655
  • 1
  • 30
  • 43
user537638
  • 91
  • 1
  • 1
  • 2

5 Answers5

21

In python classes are just objects that can be changed at runtime. So for example:

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

but you don't want to do things like this or whoever will have to maintain or debug this program for sure will try to kill you (and this guy will be probably yourself)

NOTE: per-instance customization of special "dunder" methods doesn't work (because of an internal Python optimization). The workaround is to have the special method call a regular method and then do the per-instance customization on that one. See Why won't dynamically adding a `__call__` method to an instance work? for details.

6502
  • 112,025
  • 15
  • 165
  • 265
5

Everything is possible, you can do stack manipulation and insert bytecode in runtime. See stuff like byteplay.

But why??

Such modification is unintuitive and unreadable, it's better if you leave x += obj3 there in first place, and set obj3 to 0; When you need that line to do something, you use a nonzero value on obj3...

nosklo
  • 217,122
  • 57
  • 293
  • 297
2

Change functionality of a method during runtime is what programs do all the time. It's called "generalizing."

All you do is write a more general algorithm. It's not hard.

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 )

There is no place for "run-time" code changes. That's wrong.

There correct thing to do is write a more general algorithm.

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • ok, summation was just an example, how to generize this, is what i wanted to know! – user537638 Dec 10 '10 at 11:10
  • @user537638: "summation was just an example ". You don't modify code at run time. You write the more general algorithm. In this case, I wrote a more general algorithm. In **all** cases (**all**) you write the more general algorithm. – S.Lott Dec 10 '10 at 11:24
  • that would be ideal situation, however sometimes i do not know what the user would like to change! my users(scientists) sometimes want to change statments, methods, etc, to suit thier 'minds' - Thanks for the feedback! – user537638 Dec 10 '10 at 11:30
  • 2
    @user537638: "i do not know what the user would like to change!" Then that's not "at runtime". That's a conversation and a design change. If you want a design that allows flexibility, then, you need to design for flexibility. Study Object-Oriented Programming and Functional Programming to learn about more flexible (and more generalized) designs. – S.Lott Dec 10 '10 at 11:34
  • @user537638 But don't get into the habit of coding for the unknown future. Solve the problem at hand. – progmatico Jul 14 '19 at 19:45
1

(As of what i know) There are some, but limited ways in which someone could achieve what you specifically want...

Mainly described by the phrase "Monkey Patching" (as also mentioned by others here) or when generally speaking of code manipulation and/or execution in runtime, usually also referred to by the phrase of "dynamic/runtime code execution" [...]

As in python, you could do something along the following or simply the following, lines:

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

which outputs:

Before: 10
After : 12

⚠️ Disclaimer: this is not a recommendation (at least not for all use cases), this is just an approach, a proof of consept as it is indeed a working one ( and so pls don't hate me for it.)

Giorgos Xou
  • 1,461
  • 1
  • 13
  • 32
0

It's not completely clear what you want to do, but changing methods and classes at runtime is called "Monkey Patching", and is frowned on in Python (as the name suggests).

The reason is because it makes your code extremely hard to debug since there's easy to tell just by reading code which version of a method is being called. Or what is more likely, the person performing the debugging won't even realise the method has been changed and so can make sense at all of the behaviour they're seeing.

So whilst you can change methods dynamically, it's best if you don't. If you give more details about the problem you are trying to solve, someone will be able to suggest a more "Pythonic" solution.

David Webb
  • 190,537
  • 57
  • 313
  • 299