Does python support multi prototype.

A

angel

Hi

Java and cpp support one function name multi function prototype.
For example:
A:
int func1(String s){}
int func1(int i){}

B:
int func1(String s){}
int func1(String s, int i){}

Does python support it?

Thanx
 
C

Chris Dutton

angel said:
Hi

Java and cpp support one function name multi function prototype.
For example:
A:
int func1(String s){}
int func1(int i){}

B:
int func1(String s){}
int func1(String s, int i){}

Does python support it?

No, but it doesn't have to. The type of a function's arguments are not
statically limited.

def foo(bar):
print bar

I can call this as easily with one type as with another:

foo(1)
foo("baz")

As for the number of arguments a function takes, it's possible to use
the * operator to slurp extra arguments up into a list.

def foo(bar, *extras):
...

foo(1)
foo("baz")
foo("baz", "hello", "world")
 
J

Jorgen Grahn

To be pedantic, C++ is called "C++", not "cpp", and what you seem to refer
to is what C++ calls "overloaded function names" or "overloading".

....
No, but it doesn't have to. The type of a function's arguments are not
statically limited.
....

Yes, but that's not as elegant in cases where the arguments' types has to
trigger very different processing. I can even imagine situations where
foo(S) and a foo(T) do completely different things, and still 'foo' is the
best name for both of them.

I miss overloading in Python from time to time, but I can live without it.
It is, after all, closely tied to a type system which is desirable in C++
and Java, but not in Python.

/Jorgen
 
P

Peter Hansen

Jorgen said:
Yes, but that's not as elegant in cases where the arguments' types has to
trigger very different processing. I can even imagine situations where
foo(S) and a foo(T) do completely different things, and still 'foo' is the
best name for both of them.

I miss overloading in Python from time to time, but I can live without it.
It is, after all, closely tied to a type system which is desirable in C++
and Java, but not in Python.

(untested code, may be minor bugs)

def _foo_S(arg):
# do something with arg, which is an S

def _foo_T(arg):
# do something with arg, which is a T

def _foo_whatever(arg):
# do something with arg when it's a "whatever"

# ad nauseum...

def foo(arg):
'''generic dispatcher for foo() function'''
try:
func = globals()['_foo_%s' % type(arg).__name__]
except KeyError:
raise TypeError('invalid type for function foo', arg)
else:
func(arg)


If you _really_ miss it from time to time, then it's _really_
easy to add it so that it's available in a fairly elegant fashion
when you do need it.

The above won't handle old-style classes, but adding support
for them would be pretty trivial too. (Just need to check for
the case where the type is "instance" and use arg.__class__
instead of type(arg).)

-Peter
 
C

Chris Dutton

Jorgen said:
...

Yes, but that's not as elegant in cases where the arguments' types has to
trigger very different processing. I can even imagine situations where
foo(S) and a foo(T) do completely different things, and still 'foo' is the
best name for both of them.

So use the existing control flow structures to decide which set of code
to execute at runtime. It's certainly not going to be as efficient as a
compiled language which can make the distinction at compile time, but
it's easily as elegant a way of thinking about the problem.

def foo(bar):
if (isinstance(bar, int)):
...
elif (isinstance(bar, str)):
...
else
...

Now, if only Python had a smart "switch" style construct like Ruby or
Groovy, since "isinstance" hurts my eyes. :)

def foo(bar)
case bar
when Integer
...
when String
...
else
...
end
end
 
J

Jorgen Grahn

Jorgen Grahn wrote: ....

(untested code, may be minor bugs) ....

If you _really_ miss it from time to time, then it's _really_
easy to add it so that it's available in a fairly elegant fashion
when you do need it.

Well, I don't _really_ miss overloading that much. Not enough to try to
squeeze it into Python when I know it's an idiom that doesn't really fit.

Your code was kind of elegant, but kind of misses the point with
overloading, I think. At least, it's not anything I'd want to do in most
situations where overloading would have been nifty in C++. IMHO.

/Jorgen
 
P

Peter Hansen

Jorgen said:
Your code was kind of elegant, but kind of misses the point with
overloading, I think. At least, it's not anything I'd want to do in most
situations where overloading would have been nifty in C++. IMHO.

Okay, fair enough. Would you be able to describe any situation
in which you have found overloading to be useful in C++. (Note,
not merely nifty, but useful?) In my experience, most of the
cases where I used it in C++ were actually cases of poor design
and should have been done differently, in hindsight.

-Peter
 
J

Jorgen Grahn

Okay, fair enough. Would you be able to describe any situation
in which you have found overloading to be useful in C++. (Note,
not merely nifty, but useful?)

Well, it's needed for output streams to work -- the << operators which push
objects onto streams cannot be member functions - and they better have the
same "names".

I also suspect it's vital to generic programming using templates and such ...

Also when you want common functions that operate on objects without being
members -- the thing Python solves by translating len(x) to x.__len__() etc.
In my experience, most of the
cases where I used it in C++ were actually cases of poor design
and should have been done differently, in hindsight.

If we are talking member functions, you may have something there ...
On the other hand, I don't see embedding a type name in the method name as a
better alternative, ever.

I wrote a small Python helper class yesterday, for reasons too complicated
to explain here. I called it "Cluster", and it was really just a set of
(x,y) points which I expected to be roughly clustered around some point.
I needed to find the distance between (the center of) a Cluster and a point,
but also between two Clusters.

Had that been C++, I would have been tempted to add two methods:
double Cluster::distance(const Cluster&) const;
double Cluster::distance(const Point&) const;
but for some reason (asymmetry?) that feels like the easy and slightly wrong
way out.

Anyway, this was Python so I didn't have to think much about that ;-)

/Jorgen
 
X

xtian

Matteo Dell'Amico said:
angel said:
Java and cpp support one function name multi function prototype. [...]
Does python support it?

Not natively, but - if you really need them - there are modules that
make them possible.

Have a look at
http://gnosis.cx/publish/programming/charming_python_b12.html , and
maybe at
http://codespeak.net/pypy/index.cgi?doc/objspace/multimethod.html too.

One thing to note is that these Lisp-ish multimethods are more
powerful than Java- or C#-style method overloading, because the method
dispatch is done at runtime using the actual types of the arguments.
In Java and C# overload selection is done at compile time, so if
you've got, frex:

public class Thing {
public void DoSomething(Integer val) {
...
}

public void DoSomething(String val) {
...
}

public void DoSomething(Object val) {
...
}
}


[and then]

Object o = "fish";
Thing t = new Thing();
t.DoSomething(o);

.... you'll always get the object version of DoSomething called,
because the declared type of o is Object.

Which always annoyed me.

xtian
 

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
474,202
Messages
2,571,057
Members
47,666
Latest member
selsetu

Latest Threads

Top