Python 27: How to fix/store a value to a method to preserve its interface?
<p>If everything is an object in python then why does the following not work?</p>

<pre><code>class Hello(object):

    def hello(self):
        print(x)

h = Hello()
h.hello.x = "hello world"
</code></pre>

<p>When doing this I get:</p>

<pre><code>AttributeError: 'instancemethod' object has no attribute 'value'
</code></pre>

<p>A way which I can achieve this is by using partial however I am not sure what the effects of that would be on an object. Is there another way to achieve this?</p>

<pre><code>from functools import partial
class Hello(object):

    def hello(self, x):
        print(x)

h = Hello()
newMethod = partial(h.hello, "helloworld")
newMethod()
</code></pre>

<p>Okay, from the comments below, people want a "real" scenario one example which can be considered as the following:</p>

<pre><code>file.txt contains the following list
["ItemID1", "ItemID2", "ItemID3", "ItemID4"]

def BindMethods(self):
    # ["ItemID1", "ItemID2", "ItemID3", "ItemID4"]
    items = readFromFile("file.txt")
    self.bind(AN_EVENT, GenericMethod)

 def GenericMethod(self, i, event):
     # The person calling this method knows that the method
     # only accepts a single argument, not two.
     # I am attempting to preserve the interface which I do not have control over
     data = generateDataFromID(i)
     table[i] = data
</code></pre>

<p>The idea here being that you bind a method to an event whereby the caller is expecting the method of a specific signature i.e. a single input argument.</p>

<p>But at the point of binding you want to pass in some extra information down to the handler. You don't know how much information you want to pass down since it is variable.</p>

<p>A expanded/compile time version of the same thing would be something like this:</p>

<pre><code>file.txt contains the following list
["ItemID1", "ItemID2", "ItemID3", "ItemID4"]

def BindMethods(self):
    # ["ItemID1", "ItemID2", "ItemID3", "ItemID4"]
    items = readFromFile("file.txt")
    self.bind(AN_EVENT, self.Item1Method)
    self.bind(AN_EVENT, self.Item2Method)
    self.bind(AN_EVENT, self.Item3Method)
    ......

 def Item1Method(self, event):
     data = generateDataFromID("Item1")
     table["Item1ID"] = data

 def Item2Method(self, event):
     data = generateDataFromID("Item2")
     table["Item2ID"] = data
</code></pre>

<p>After your edit, this seems to me as if you seek a possibility to <em>route</em> certain events to certain functions, right?</p>

<p>Instead of binding new attributes to existing <em>instance methods</em>, you should think about setting up a clean and extendable event routing system.</p>

<h2>A Basic Routing Core</h2>

<p>While usually application of the <code>singleton</code> pattern always is a good point to ask oneself whether one is following the right concept, it totally makes sense here. The core of your routing is something similar to this:</p>

<pre><code>def singleton(cls):
    instance = cls()
    instance.__call__ = lambda: instance
    return instance

@singleton
class EventRouter(object):
    def __init__(self):
        self._routes = dict()

    def bind(self, key, func):
        self._routes[key] = func

    def route(self, key):
        if key in self._routes.keys():
            return self._routes[key]()
        else:
            raise KeyError('Unbound routing key: {}'.format(key))
</code></pre>

<p>The <code>EventRouter</code> is a singleton class that can bind functions to certain keys and is furthermore able to route occurring events to their desired destination functions.<br>
You now kan bind an event to a desired function during runtime:</p>

<pre><code>def my_event_function():
    print('An event was handled.')

EventRouter.bind('E_MYEVT', my_event_function)

# If you are iterating over events (for example drawn from a file),
# you can direct them to their functions:
for e in ['E_MYEVT', 'E_WHATEVT', 'E_NOEVT']:
    EventRouter.route(e)
</code></pre>

<h2>A Routing Decorator</h2>

<p>If required, you can set up another decorator that can be used to directly bind methods to a certain event type:</p>

<pre><code>def eventroute(key):
    def register_method(call):
        EventRouter.bind(key, call)
    return register_method

@eventroute('E_MYEVT')
def handle_myevt():
    print('Handling event: E_MYEVT')

@eventroute('E_WHATEVT')
def handle_whatevt():
    print('Handling event: E_WHATEVT')

if __name__ == '__main__':
    for e in ['E_MYEVT', 'E_WHATEVT']:
        EventRouter.route(e)

&gt;&gt;&gt; Handling event: E_MYEVT
&gt;&gt;&gt; Handling event: E_WHATEVT
</code></pre>

<h2>Passing Arguments to the Route Endpoints</h2>

<p>If you want to pass arguments to the endpoints, just extend the calls by optional keyword arguments <code>**kwargs</code> when forwarding the call:</p>

<p>In <code>EventRouter</code> class, change <code>route</code> method to:</p>

<pre><code>def route(self, key, **kwargs):
    if key in self._routes.keys():
        return self._routes[key](**kwargs)
    else:
        raise KeyError('Unbound routing key: {}'.format(key))
</code></pre>

<p>For your endpoints, set the desired arguments. In this example, I use the argument <code>filename</code>:</p>

<pre><code>@eventroute(...)
def handle_...(filename):
    print('Handling event: ...')
    print(filename)
</code></pre>

<p>And when dispatching your events, provide the required argument as kwarg:</p>

<pre><code>events = ['E_MYEVT', 'E_WHATEVT']
for e in events:
    EventRouter.route(e, filename='whatever.jpg')

&gt;&gt;&gt; Handling event: E_MYEVT
&gt;&gt;&gt; whatever.jpg
&gt;&gt;&gt; Handling event: E_WHATEVT
&gt;&gt;&gt; whatever.jpg
</code></pre>

<h2>Where to go</h2>

<p>This is a brief overview of just a very basic setup.<br>
You can extend your <code>EventRouter</code> to be arbitrarily complex, e.g. add routing keys in a multi-layered hierarchy, or the like. Furthermore, you can add more arguments to your methods. You can even think about extending the <code>eventroute</code> decorator to define the <code>kwargs</code> that shall be passed to the endpoint function to keep the function signatures as generic as possible.</p>

<p>Might seem like overkill, but structures like these are pretty neat and can be extended by anyone who imports your library/script and wants to add her own endpoints for individual events.</p>

python python-2.7