Thursday, May 16, 2013

How does Python identify the type?

In the CS101 forum, a student noticed that types significantly influence the computations in python, but that we generally don't declare types in Python. They wondered how this can be so.

In the speed of the light question,when the prof changed the value of 1 to a float value 1.0,the answer was much more accurate,i want to know , how and why in python unlike other languages,there is no need to define the type?

To see the original discussion thread, see:

My reply to that question:

In Python, variable names have values and values have types. So if I say x=2, the type of the value of x is int. I can then say x="dog" and now the type of the value of x is string. Python knows the type of a literal in the source from the syntax (e.g. quotes to make something be a string value, or square brackets to make something be a list or curly brackets to make something be a dictionary. Number without a decimal point for an integer. Number with a decimal point for a float. At runtime, all the values of variables in memory have a specific type. Operations on those values therefore have methods that know how to work with those types (or an exception is thrown), and produce results of a specific type.

Python might not know what that type is until runtime, but hopefully the programmer knows what they meant to produce and gets it right. Other languages ("bondage and discipline languages") are much more demanding that all be declared at compile time, but then you might end up with a procedure that you'd like to use on an object in your program, but get snagged that although the object behaves like you need it to, it isn't the exact type that the procedure was coded to expect. Python says "if it walks like a duck and it quacks like a duck, then it's a duck" (Hence, "duck typing"). So if the object provides whatever operations are needed for the procedure, you're good to go.

Broad categories of types include orderable types for which lt and eq (comparison) operations are defined. Another broad category is "iterables". You can easily write a procedure in Python that'll happily operate on any type that meets the requirements of the procedure. e.g. if you can compare objects of the given type and decide how to put them into order (i.e. which is "greater" and which is lesser), then you can probably feed objects of that type to your sort procedure - even types that you created long after you wrote the sort procedure. If you write a procedure that takes an iterable, it can be written to be happy with a list or a file or a generator (a special kind of procedure that returns a value but that you can then resume to get the next value) - and the procedure can be happy as you apply it in amazing new ways.

That's one of the definite sources of the power of Python. This type freedom has its downsides too, such as there being surprisingly little that can be statically verified about a piece of Python code. At "compile time", Python doesn't really know what is going to happen at run time. If I was implementing a nuclear reactor control system, I think I'd feel safer writing it in Ada, not Python. But, most days I definitely am not writing nuclear reactor control software or anything that could seriously kill someone if it has a flaw. That sort of software puts a seriously literal meaning into the phrase "fatal flaw". For a reminder of how fatal a software flaw can be, see: An Investigation of the Therac-25 accidents.

Here's a highly technical talk related to this topic of types which I hardily recommend. Have a pad and pencil handy as you watch it and jot down things he mentions that you don't know about, then Google for more info on those words later. Dynamic Languages Strike Back. After you are more comfortable with those words, you might even want to watch the video again.