How to make a function associated with a class?

dbpokorny at gmail.com dbpokorny at gmail.com
Tue Jul 1 17:50:40 EDT 2008


On Jul 1, 1:43 pm, Kurda Yon <kurda... at yahoo.com> wrote:
> Hi,
>
> I have a class called "vector". And I would like to define a function
> "dot" which would return a dot product of any two  "vectors". I want
> to call this function as follow: dot(x,y).
>
> Well, I can define a functions "dot" outside the class and it works
> exactly as I want. However, the problem is that this function is not
> associated with the class (like methods a method of the class).
>
> For example, if I call "x.calc()" or "y.calc()", python will execute
> different methods if "x" and "y" belongs to different classes. I want
> to have the same with my "dot" function. I.e. I want it calculates the
> dot product ONLY IF the both arguments of that function belong to the
> "vector" class.
>
> Is it possible?
>
> Thank you in advance.

It sounds like you are talking about data-directed programming (see
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-17.html#%_sec_2.4.3).
Basically you have two options:

def dot(x,y):
  if isinstance(x,Vector) and isintance(y,Vector):
    ...
  raise TypeError("...")

which quickly breaks down in a mess of if-then clauses when you want
to expand the dot function to handle other datatypes, or you create a
table and populate it with entries like this
dispatch_table[('dot','Vector','Vector')] = Vector.dot # this has to
be declared @staticmethod in class Vector
dispatch_table[('dot','str','str')] = operator.add # borrowed from PHP
dispatch_table[('mul',Matrix,Matrix)] = Matrix.mul

You now have to write something like this (this isn't even valid
Python code, but hopefully you get the idea)

def generic_function(name):
  def exec_generic_function(*args):
    f = dispatch_table.get((name, *(type(arg).__name__ for arg in
args)),None)
    if f == None:
      raise TypeError('...')
    return f(*args)
  return exec_generic_function

dot = generic_function('dot')

# NB: (a, *b) means (a,) + b until the generalized *-unpacking syntax
is accepted

This is essentially a translation into Python of the content of the
link.

Neither of these options are great (and the latter is marginal at
best) if you care about performance (but maybe it will all become C
anyway so you don't care). If you want to do it the Python way, use
__mul__.

Cheers,
David



More information about the Python-list mailing list