How to make a function associated with a class?

K

Kurda Yon

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.
 
B

bruno.desthuilliers

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?

You don't need to make dot() a method of your Vector class to have
this behaviour, and making it a method of the Vector class isn't
enough to have this behaviour.

The simplest solution would be:

class Vector(object):
def dot(self, other):
if not isinstance(other, type(self)):
raise TypeError("can only calculate the dot product of two
vectors")
# do the job here and return what's appropriate

Now since it's a binary operator, you might as well implement it as
such:

class Vector(object):
def __mul__(self, other):
if not isinstance(other, type(self)):
raise TypeError("can only calculate the dot product of two
vectors")
# do the job here and return what's appropriate

Then use it as doproduct = vector1 * vector2


HTH
 
K

Kurda Yon

You don't need to make dot() a method of your Vector class to have
this behaviour, and making it a method of the Vector class isn't
enough to have this behaviour.

The simplest solution would be:

class Vector(object):
def dot(self, other):
if not isinstance(other, type(self)):
raise TypeError("can only calculate the dot product of two
vectors")
# do the job here and return what's appropriate

Now since it's a binary operator, you might as well implement it as
such:

class Vector(object):
def __mul__(self, other):
if not isinstance(other, type(self)):
raise TypeError("can only calculate the dot product of two
vectors")
# do the job here and return what's appropriate

Then use it as doproduct = vector1 * vector2

HTH

As far as I understood, In the first case, you gave, I need to call
the function as follows "x.dot(y)". In the second case I need to call
the function as follows "x*y". But I want to call the function as
follows "dot(x,y)".

By the way, "type(self)" returns the name of the class to which the
"self" belongs?
Does "instance" return "true" if the first argument belongs to the
class whose name is given in the second argument?
 
D

dbpokorny

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
 
D

dbpokorny

By the way, "type(self)" returns the name of the class to which the
"self" belongs?
Does "instance" return "true" if the first argument belongs to the
class whose name is given in the second argument?

$ python
Python 2.5.1 (r251:54863, Oct 30 2007, 13:54:11)
[GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
help(type) [...]
help(isinstance)
[...]
 
J

John Roth

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.

If I understand what you want, you could do it the same way most of
the other functions are implemented. There's a function, and then each
class which has the behavior has a private (actually a system) method
that implements it.

The general pattern is to get the class for the first operand, check
to see if it has the implementation method, and call it if present. If
it doesn't, get the class for the other operand, check and if it has
the method call it with the operands reversed.

Then if it isn't in either, you can look the actual implementation
method up in a table. When all else fails, raise a type error.

HTH

John Roth
 
B

Bruno Desthuilliers

Kurda Yon a écrit :
As far as I understood, In the first case, you gave, I need to call
the function as follows "x.dot(y)". In the second case I need to call
the function as follows "x*y". But I want to call the function as
follows "dot(x,y)".

I tought you could figure it out by yourself from the above examples.

By the way, "type(self)" returns the name of the class to which the
"self" belongs?

Nope, it returns the class object (for new-style classes at least).
Does "instance" return "true" if the first argument belongs to the
class whose name

Python's classes are objects. type() returns a class object (or a type
object for old-style classes IIRC), and isinstance() takes a class or
style object (or a tuple of class / type objects) as second argument.
is given in the second argument?

isinstance() is documented, you know ? As well as type() FWIW. What
about first looking up the fine manual, then come back if there's
something you have problem with ?-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,228
Latest member
MikeMichal

Latest Threads

Top