2

I have a dictionary of methods:

def name(self):
   print self.name

def age(self):
   print self.age

display = {
   'name': name,
   'age': age
}

And I have a class Person where I want display['name']() and display['age']() to work as methods:

class Person:
   def __init__(self):
      self.name = 'Bob'
      self.age = 22
      self.showName = display['name']
      self.showAge = display['age']

person = Person()

The problem is that when I call person.showName() I get the error

TypeError: showName() takes exactly 1 argument (0 given)

How can I make the function showName act like a method, and implicitly pass self as the first argument?

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • possible duplicate of [add method to loaded class/module in python](http://stackoverflow.com/questions/7749914/add-method-to-loaded-class-module-in-python) – Björn Pollex Jan 18 '12 at 13:34
  • Sorry, misread the question - it's not a duplicate of that one. – Björn Pollex Jan 18 '12 at 13:34
  • Are you aware of the difference between a class-method and an instance-method? Is the wording in the title deliberate, or are you confusing something? – Björn Pollex Jan 18 '12 at 13:36
  • I guess it is a duplicate of [this one](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object) instead. – Björn Pollex Jan 18 '12 at 13:36
  • @BjörnPollex: I'm probably confused with something. :) Python is very new to me. Feel free to edit the title, I'll accept the change. – Randomblue Jan 18 '12 at 13:36

4 Answers4

4

Easy way is to move definitions of your functions outside of __init__:

>>> class Person:
...     showName = display['name']
...     showAge = display['age']
...     def __init__(self):
...             self.name = 'Bob'
...             self.age = 22
...
>>> Person().showAge()
22

Harder way is to understand why does this happens and use MethodType:

>>> class Person:
...     def __init__(self):
...             self.name = 'Bob'
...             self.age = 22
...             self.showName = types.MethodType(display['name'], self)
...             self.showAge = types.MethodType(display['age'], self)
...
>>> Person().showAge()
22

In short, a function should be a method to be threaten a bit special while performing object.attribute lookup. This threatening also includes passing of self parameter, which your functions expect. MethodType takes function and binds it to some object thus creating a method.

First example works since functions defined along with class definition are threaten as methods automatically.

Roman Bodnarchuk
  • 29,461
  • 12
  • 59
  • 75
1
from functools import partial
class Person:
   def __init__(self):
        self.showName = partial(display['name'], self=self)

partial allows better support for passing arguments to the encapsulated function than lambda, if you'll have any need for more arguments in the future.

dorsh
  • 23,750
  • 2
  • 27
  • 29
  • 2
    While this works, there is a [better solution](http://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object). – Björn Pollex Jan 18 '12 at 13:39
0

You can use something like:

self.showName = lambda : display['name'](self)
karolx
  • 508
  • 4
  • 9
-2

Do this:

display['name']()

Should work.

TyrantWave
  • 4,583
  • 2
  • 22
  • 25