0

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 :(

3
  • 1
    where are you trying to type check a Commented Dec 9, 2016 at 18:28
  • Can you edit your question and post the code when it gives that error, including the type(a) call Commented Dec 9, 2016 at 18:28
  • Not a solution to the problem with your solution. But I think you might want to check out mypy which I've written about in my answer here: stackoverflow.com/a/21384492/965332 Commented Jun 22, 2017 at 18:22

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok. If I gave a and b defined values, such as a=10 and b=23, would that mean then that they were "defined"? How then would I make sure that a and b were usable outwith the function...? Would that involve altering their scope from local scope to global scope?
altering scope of a variable wont make it type defined. Python by default does not support type definition. You cant have a variable in your code who's datatype can't be changed. Only thing you can do which is bad practice is checking datatype of variable inside your function and making sure it doesn't get passed any other datatype.
I am aware it is "bad practice". I clearly stated that at the beginning, I merely posed the question due to the fact that it was one of the questions in the textbook that I am teaching myself from.
Understood. The thing is I won't suggest something like that without adding the concerns attached with it. Thanks for accepting the answer. Hope it helped :)
Absolutely, that's why I accepted your answer, precisely because you DID add those concerns :)
1

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.

3 Comments

Actually, I am a total novice, with no programming language exp. at all, merely teaching myself Python before embarking on it in earnest at university. :)
Aha, well good for you! I hope this helps then, and good luck!
PS: I had already voted for someone else, but, if I could do it again, I'd vote for you too! Very very helpful comment!
0

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.

1 Comment

Ok, I merely stated "checking type of parameters" because that is my intended objective, and I was and am unsure as to what I am doing wrong, so as such, this falls under the category of "good faith" error.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.