[ACCEPTED]-Assigning a function to an object attribute-methods

Accepted answer
Score: 18

Here is how you do it:

import types
class Scriptable:
    def __init__(self, script = None):
        if script is not None:
            self.script = types.MethodType(script, self)   # replace the method
    def script(self):
        print("greetings from the default script")

As ba__friend noted 7 in the comments, methods are stored on the 6 class object. A descriptor on the class object 5 returns functions as bound methods when 4 you access the attribute from a instance.

When 3 you assign a function to a instance nothing happens 2 special happens, so you have to wrap the 1 function yourself.

Score: 11

Thanks to Alex Martelli's answer here is another 1 version:

class Scriptable:
    def script(self):
        print(self)
        print("greetings from the default script")

def another_script(self):
    print(self)
    print("greetings from the another script")

s = Scriptable()
s.script()

# monkey patching:
s.script = another_script.__get__(s, Scriptable)
s.script()
Score: 7

Look at this:

>>> scriptable = Scriptable()
>>> scriptable.script
<bound method Scriptable.script of <__main__.Scriptable instance at 0x01209DA0>>
>>> scriptable = Scriptable(my_script)
>>> scriptable.script
<function my_script at 0x00CF9730>

Statement self.script = script creates only an 8 attribute of a class object, without any 7 'magic' with it.

Statement def script(self): inside a class 6 definition creates a descriptor - special 5 object that actually manages all stuff with 4 the self parameter.

You can read more about descriptors 3 in Python in the mentioned Data model reference: implementing-descriptors.

One 2 more great article about descriptors in 1 Python from Raymond Hettinger: How-To Guide for Descriptors.

Score: 1

I can't really answer your question why it 3 works like that, you'll have to ask Guido 2 van Rossum, but I can give you a possible 1 workaround:

class Scriptable:
    def __init__(self, script = None):
        self._script = script # replace the method
    def script(self):
        if self._script: return self._script(self)
        return self._defaultscript()
    def _defaultscript(self):
        print("greetings from the default script")

More Related questions