Function parameter type safety?

R

Robert Dailey

Hi,

Is there a way to force a specific parameter in a function to be a
specific type? For example, say the first parameter in a function of
mine is required to be a string. If the user passes in an integer, I
want to notify them that they should pass in a string, not an integer.
 
L

Larry Bates

Robert said:
Hi,

Is there a way to force a specific parameter in a function to be a
specific type? For example, say the first parameter in a function of
mine is required to be a string. If the user passes in an integer, I
want to notify them that they should pass in a string, not an integer.

There is, but be careful. What about a string-like object, why would you want
to fail on that. It is better to attempt to do whatever you want to do with the
string and catch the exception.

Possible solution that I don't really like, but meets your explicit requirement:

def foo(arg1):
if isinstance(arg1, (basestring, unicode):

print "is string"
else:
print "is NOT string"

return


-Larry
 
S

Steven Bethard

Robert said:
Is there a way to force a specific parameter in a function to be a
specific type? For example, say the first parameter in a function of
mine is required to be a string. If the user passes in an integer, I
want to notify them that they should pass in a string, not an integer.

In Python, you generally don't want to do this. If I have code like::

def foo(x):
if not isinstance(x, basestring):
raise ValueError('x must be a string')
return x.split()

then if someone creates a string-like object that doesn't subclass from
basestring, my code raises an exception even though the string-like
object had a .split() method and would have worked perfectly. If you
really feel like you need to give a specific error message, you could
write it instead like::

def foo(x):
try:
split = x.split
except AttributeError:
raise ValueError('x needs to have a split() method')
return split()

But generally there's no reason to do that because the AttributeError
itself would have said almost exactly the same thing.

Long story short: checking parameter types is un-Pythonic. Don't do it.

STeVe
 
D

Dave Baum

Robert Dailey said:
Hi,

Is there a way to force a specific parameter in a function to be a
specific type? For example, say the first parameter in a function of
mine is required to be a string. If the user passes in an integer, I
want to notify them that they should pass in a string, not an integer.

At present, there isn't any built-in way to do this (see the recent
thread "PEP 3107 and stronger typing" for a long discussion).

However, you can use assert and isinstance() to check it manually:

def foo(a):
assert isinstance(a, str), "argument 'a' must be a string"


I wouldn't advocate getting carried away with this pattern since it
precludes your function from working with duck typing and defeats some
of the dynamic nature of Python. On the other hand, without such checks
the resulting exceptions from assuming an argument is one type when it
is another can be a bit misleading.

Dave
 
B

Bruno Desthuilliers

Robert Dailey a écrit :
Hi,

Is there a way to force a specific parameter in a function to be a
specific type?

No, and that's considered a GoodThing(tm).
For example, say the first parameter in a function of
mine is required to be a string. If the user passes in an integer, I
want to notify them that they should pass in a string, not an integer.

Document the fact that the function expects a string as it's first
param. If someone pass an int, it's likely that he'll soon find out
there's something wrong (either from an exception or from obviously
incoherent results). This is usually enough.

If you're in the case that passing a non-string will not raise an
exception in the function but just lead to strange results or raise
somewhere else, you can eventually use an assertion to ease debugging -
but don't get into the habit of systematically type-check functions
arguments, this would be fighting against the language.

My 2 cents...
 
R

Robert Dailey

Good replies.

I'm in the process of learning Python. I'm a native C++ programmer, so
you can see how the question relates. There's a lot of cool things C++
allowed you to do with type-checking, such as function overloading.
With templates + type checking, I can create a STD version of ifstream/
ofstream in Python. However, I found it isn't possible since Python
mainly works with strings in file data instead of bytes. To write a
number 400000 to a file in python would take 6 bytes instead of 4, for
example. Anyway, I just wanted to explain why I was asking about type
checking. There's other measures I'm willing to take to get my job
done. Thanks guys.
 
M

Michele Simionato

Good replies.

I'm in the process of learning Python. I'm a native C++ programmer, so
you can see how the question relates. There's a lot of cool things C++
allowed you to do with type-checking, such as function overloading.

This is an area of hot debate in Python and things are changing. You
may want
to have a look at http://www.python.org/dev/peps/pep-3119 about
interfaces,
and to http://www.python.org/dev/peps/pep-3124 about overloading and
generic functions. Both PEPs are for Python 3000, but their existence
should be an indication that people are not happy with the current
situation
in Python. You can something better than overloading already, with
P.J. Eby
modules simplegeneric and/or RuleDispatch, but I would say that they
are not
commonly used. So the right thing to do for now is to follow the good
advices you received, but keep in mind that there will be alternatives
in
the near future (such as interface checking/function overload).

Michele Simionato
 
G

Gabriel Genellina

However, I found it isn't possible since Python
mainly works with strings in file data instead of bytes. To write a
number 400000 to a file in python would take 6 bytes instead of 4, for
example.

py> import struct
py> f = open("output.bin","wb")
py> f.write(struct.pack("l", 400000))
py> f.close()
py> ^Z


C:\TEMP>dir output.bin
El volumen de la unidad C no tiene etiqueta.
El número de serie del volumen es: 3828-F1AF

Directorio de C:\TEMP

14/07/2007 00:13 4 output.bin
1 archivos 4 bytes
0 dirs 18.806.763.520 bytes libres

"strings" are "strings of bytes" in Python. (If you are mostly concerned
with characters, use unicode objects).
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top