apronedsamurai
apronedsamurai

Reputation: 73

checking type of the parameters of a function in python

In the first instance, I am aware that this is a source of contention within Python community, namely that type checking is indicative of poor code etc etc. However, its part of my learning experience, and I am wanting to have another skill in my Python toolset.

def do_plus(a,b):
    result=a+b
    return result
calculated_result=do_plus(12,34567)
print (calculated_result)

calculated_result=do_plus(12,34567)
print (calculated_result)

Now, when I try:

type(calculated_result) 
type (do_plus)

I get int and function respectively.

type (do_plus(a))

the above results in:

"Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    type (do_plus(a,b))
NameError: name 'a' is not defined"

I am confused by this, surely I have defined a and b within the parenthesis after def do_plus?

The reason I want the type for parameters is to a spot check, i.e. check the type, and if it is not correct, raise a TypeError, regrettably, I am failing at the 1st hurdle it seems :(

Upvotes: 0

Views: 2284

Answers (3)

Alex Van Liew
Alex Van Liew

Reputation: 1369

I think your problem comes from a misunderstanding of how variable typing works in Python. In the line

type(do_plus(a))

The reason it complains about a not being defined is because it's not looking at the parameter a, it's looking for a variable called a that it's trying to pass to the function.

In python, method parameters aren't strongly typed. You cannot know what types a method expects just by looking at the signature! I assume you come from a static-typed language where you can use reflection or a similar trick to inspect the parameters declared for the method, but no such functionality exists in python because it doesn't make sense. For example, I can do this:

do_plus(1, 2) # parameters are both `int`
>>> 3
do_plus(1.1, 2.2) # parameters are both `float`
>>> 3.3
do_plus("string1", "string2") # parameters are both `str`
>>> "string1string2"
do_plus("string", 3) # one parameter is `str`, one is `int`
>>> "string3"
do_plus(3, "string")
>>> TypeError: unsupported operand type(s) for +: 'int' and 'str'

Notice that in the last line, the complaint isn't "You can't call this method with these parameters", the complaint is "I don't know how to calculate 3 + "string"". If you look at the stack trace, it will complain about the line inside do_plus, which indicates that execution entered the function successfully.

So, since you can't type check from outside the function, you have to type check inside. You can do this with the isinstance built in function:

def do_plus(a, b):
  if not isinstance(a, int) or not isinstance(b, int):
    raise TypeError("do_plus only accepts ints")
  return a + b

This is because of one of the core Python guidelines: "It is better to ask forgiveness than permission." Instead of checking to see if you can do something, you should try to do it and handle failure.

Other notes

The way you write type (doplus(a)) suggests to me that you think type is a keyword of some kind. This isn't the case, type is a function. Actually, it's a little more than just a function, but it is a function nonetheless. You can write

type(type)
>>> <type 'type'>

Which would lead you to conclude that type is actually a type! Of type type! This all gets very confusing very quickly, but the point is, very few words are actually reserved as keywords in Python. Most functionality you would see as keywords in other languages is done through built-in functions.

Additionally, I see you already understand this a bit, but generally instead of checking types you want to just try to do something and if it worked, then hurray! This is the beauty of duck typing, which is the idea that "if it looks like a duck and quacks like a duck, it's a duck". You should assume that any parameters people pass into your functions are going to be able to support the operations you try to perform on them; that way people can pass in other objects which support the same operations and in theory, they'll get a reasonable result just the same. It's a way of reasoning about the logic of a method instead of the implementation; the question should be "Am I doing the right thing?" not "Does this do the right thing?"

Hope this helps you. Python is a great, incredibly flexible language but it requires you to think much differently than you do in other languages.

Upvotes: 1

Vikash Singh
Vikash Singh

Reputation: 14001

In your code variable a, b are within the local scope of the method do_plus.

To understand it better lets print(type(a)) inside the method:

def do_plus(a, b):
    print(type(a), type(b))
    result = a + b
    return result

So if I call do_plus(1, 2) output is:

<class 'int'> <class 'int'>
3

But if I call do_plus(1.1, 2.0) output is:

<class 'float'> <class 'float'>
3.1

You see, The type of a, b is non existent because a and b are not defined. They are only declared as variables.

When the method is called and a is passed a float, it becomes a float. When a is passed an int, It becomes int.

Another case is say we define b=2

def do_plus(a, b=2):
    print(type(a), type(b))
    result = a + b
    return result

Here if b is passed a value wether its float or int or boolean. b will be of the datatype of that variable.

Only when b is not passed a value, then we can be 100 % sure that b is an int inside the method do_plus

This is a vary core part of python. And a good way to understand it is this code:

a = 10 
print(type(a))
a = 10.1 
print(type(a))

<class 'int'>
<class 'float'>

When variable a was assigned an int its datatype was int. When it was assigned a float its datatype changed to float.

Upvotes: 1

kindall
kindall

Reputation: 184131

Your question really has nothing to do with checking the type of parameters. It's entirely about variable scoping.

Those variables, a and b, are local to the function and exist only while the function is running. They have no meaning once the function returns. If you want to print anything involving these variables, add code to the function to do it.

Upvotes: 0

Related Questions