Discover Python, Part 1: Python's built-in numerical types

Getting started with Python, a powerful object-oriented scripting language

Level: Introductory

Robert Brunner (
Research Scientist, National Center for Supercomputing Applications
03 May 2005

The flexible nature of the Python programming language supports multiple programming philosophies, including procedural, object-oriented, and functional. But most importantly, programming in Python is fun. The language supports rather than hinders the development process. This article, the first in a series on Python programming, introduces Python and its built-in numerical types.

Python is an agile, dynamically typed, expressive open source programming language that can be freely installed on a variety of platforms (see Resources). Python code is interpreted. If you are more familiar with the edit, build, execute cycle, this might seem simplistic. But don't be fooled: Python programs can be simple scripts or large, complex programs. In fact, the very nature of the Python interpreter encourages exploration and simplifies the learning process. If you need proof, compose the classic Hello World! program in Python:

  1. Fire up the Python interpreter. (On UNIX systems, including Mac OS X, starting the interpreter usually involves typing python at a command prompt; on Microsoft® Windows® systems, you can launch a Python command shell).
  2. At the Python prompt, denoted by three greater-than symbols (>>>), enter print 'Hello World!' and press Enter.
  3. That's it: There is no third step. Listing 1 shows the output from this command.
Listing 1. Output of "Hello World" in Python

As you can see, I'm using Python V2.4 on an Apple OS X system. But the fundamentals are the same regardless of the operating system and, in this case, the actual version of Python you're using. I don't know about you, but this Hello World! exercise was a lot easier than the comparable exercises I did when I learned C, C++, or even the Java™ language. This simplicity demonstrates one of the primary benefits of using the Python interpreter. A developer can quickly try out an idea and explore an object's properties or different algorithms without having to compile, execute, and test any code.

The Python type hierarchy
One of the most important lessons to learn when transitioning to the Python programming language from another language is that everything in Python is an object. This might not seem unusual, especially if you're familiar with an object-oriented language, such as C++, Java, or C#. But Python's object-oriented philosophy goes beyond that of these other languages, as evidenced by two simple differences. First, all data values in Python are encapsulated in relevant object classes. Second, everything in a Python program is an object accessible from within your program, even the code you write.

Most popular programming languages have several built-in data types, and Python is no different in this respect. For example, the C programming language has integer and floating-point types. Given their lineage, it's not surprising that both the Java language and C# do, as well. This means that in a C program, you can write int i = 100 to create and initialize an integer variable. The same is possible in the Java language and C#, and with their auto-boxing capabilities, both of those languages can turn this simple built-in type into an Integer object when necessary.

Python, on the other hand, does not have simple types like int -- only object types. If you need an integer value in Python, you merely assign an integer value to the appropriate variable, such as i = 100. Under the covers, Python creates an integer object and assigns the variable to reference the new object. Now comes the real kicker: Python is a dynamically typed language, so you don't have to declare a variable's type. In fact, a variable's type can actually change (multiple times) during a single program.

An easy way to visualize how the dynamic typing works is to imagine a single base class called PyObject from which all other object types in Python inherit. In this model, any variable you create references an object that has been created from the overall class hierarchy. If you also have the PyObject class record the actual type, or name, of the child class, which is created and assigned to the variable, a Python program can properly determine the necessary steps to take during program execution.

The mental picture presented in the previous paragraph describing Python's object-oriented model is actually a fairly good approximation of how Python actually works. In addition, Python makes it easy to determine a variable's type, using the type function. (This example also shows how to use an inline comment with the # character.)

Listing 2. Demonstrating the Python simple types

You can classify all the Python classes below the PyObject class into four main categories that the Python run-time interpreter uses:

  • Simple types -- The basic building blocks, like int and float
  • Container types -- Hold other objects
  • Code types -- Encapsulate the elements of your Python program
  • Internal types -- Used during program execution

By the end of this series, I will have introduced all the different categories. But in this first article, I focus on the simple types.

The simple types
Python has five simple built-in types: bool, int, long, float, and complex. These types are immutable, which means that when an integer object is created, its value cannot be changed. Instead, a new simple type object is created and assigned to the variable. Using the Python id function, you can see how the identification of the underlying PyObject changes:

Listing 3. Using the Python id function

Now, this may seem like an easy way to lose objects, which would result in a memory leak. Python, like C# and the Java language, however, employs a garbage collector that frees up memory used to hold objects that are no longer referenced, like the integer object that holds 100 in the previous example.

The Boolean type
The simplest built-in type in Python is the bool type, which can hold only one of two possible objects: True or False:

Listing 4. The bool type

Because there are only two possible values, the Boolean type is unique. The Python interpreter provides the only two bool objects needed: True and False. Anytime these objects are needed in a Python program, the variable just references one as appropriate. Listing 3 shows how the bb variable has the same id whether you assign it a value of the b variable directly or just the True object directly.

Listing 5. Value of the bb variable

The case for the name of the Boolean object is important because true (and false) is undefined:

Listing 6. Undefined true and false

At this point, a bool type might not seem overly useful. However, Boolean expressions, as their name suggest, rely on them, as you see here:

Listing 7. Boolean expressions

Many programs utilize Boolean expressions, and Python provides the full range of Boolean comparison and logical operations, as detailed in tables 1 and 2, respectively.

Table 1. The Boolean comparison operators in Python

<less thani < 100
<=less than or equal toi <= 100
>greater thani > 100
>=greater than or equal toi >= 100
==equalityi == 100
!=inequality (also <>)i != 100

To be complete, the operators listed in Table 1 all have equal precedence and, unless you enclose expressions in parentheses, are applied from left to right.

Table 2. The logical operators in Python

notlogical negationnot b
andlogical and(i <= 100) and (b == True)
notlogical or(i < 100) or (f > 100.1)

The logical operators have lower precedence than the individual comparison operators, which makes sense because the comparison has to be evaluated before the logical operator can be evaluated. The actual precedence of the logical operators is given by the order these operators are presented in Table 2.

One interesting point about the or and the and logical operators in Python is that they are both shortcut operators. In simple terms, this means that given x or y, y is evaluated only if x is False. Likewise, given the expression x and y, y is evaluated only if x is True. While this functionality can improve the performance of expression evaluation -- especially for long or complex expressions -- it can also trip up programmers used to different rules learned from other languages.

The numeric types
The other four simple, built-in types in Python are all numeric types: int, long, float, and complex. Numeric types are common in programs, regardless of the language used. Python provides full support for arithmetic operations, including addition, subtraction, multiplication, and division (see Table 3).

Table 3. Arithmetic operators in Python

*multiplicationi * 100
/divisioni / 100
//integer divisioni // 100
%division remainderf % 100
+additioni + 100
-subtractioni - 100

The multiplication and division operators (the first four listed in Table 3) have higher precedence than the addition and subtraction operators. And as before, you can group sub-expressions and give them higher precedence by using parentheses to set them apart.

Unlike the Java language, which formally defines the allowed range of numeric types, Python is more like C in that the range of types is platform-dependent. You use both the int and long types to hold integer values, the difference being that an int is a 32-bit integer value. Thus, it is limited to holding values (on many platforms) from -232 to 232 - 1. In contrast, the long integer type has unlimited precision, subject to the memory limitations of your computer. To tell Python that an integer should be treated as a long, simply append an L to the end of the number, like 100L. Floating-point values in Python are always done in double precision; hence, Python float types correspond to doubles in a C-like language.

Two other important points related to the numeric types are literals, which are just explicitly expressed numbers, like 100 in the previous examples, and bit operations. Programmers typically work in the decimal system (or base 10). But sometimes other systems are more useful, especially given the binary nature of computers. Python provides support for octal (base 8) and hexadecimal (base 16) numbers. To tell Python that a number should be treated as an octal numeric literal, simply append a zero to the front. Appending a zero and an x to the front of a number tells Python to treat the number as a hexadecimal numeric literal, as the following code shows:

Listing 8. Telling Python to treat the number as a hexadecimal numeric literal

When you have an easy way to express numeric literals, especially in hexadecimal, you can easily build flags that correspond to specific test cases, which is a common programming trick. For example, a 32-bit integer can store 32 flag values. Using bit tests, you can easily test for specific flags on a flag variable. The complete list of bit operations in Python is presented in Table 4.

Table 4. Bit operators in Python

~bitwise complement~b
<<shift bits leftb << 1
>>shift bits rightb >> 1
&bitwise andb & 0x01
^bitwise exclusive orb ^ 0x01
|bitwise orb | 0x01

By now, you're probably wondering what happens when the different numerical types are mixed in a single expression. The simple answer is that Python converts all operands in an expression to the type of the most complex operand, as necessary. The complexity order is int, long, float, and complex (no pun intended), which is easily shown by an example:

Listing 9. Python conversion of all operands to the type of the most complex operand

While Python will convert the operands as you might expect, the language does not convert operands based on the operator, as shown in the 1/3 example, which evaluates to an integer. If you want to force a floating-point result, be sure that at least one of the operands is a floating-point type.

The complex type
The final type, complex, is probably not as recognizable to most programmers because it is not a common built-in data type in other programming language. To engineers and scientists, complex numbers are a familiar concept. Formally, a complex number has a real and an imaginary component, both represented by float types in Python. An imaginary number is a multiple of the square root of minus one, which is denoted by i or j -- depending on whether you were trained as a scientist or an engineer. In Python, the imaginary component of a complex number is indicated by a j:

Listing 10. Imaginary component of a complex number

This example is a complex number that has a real component of 3.0 and an imaginary component of 1.2. Notice that you can access the different parts of the complex number by using the real and imag attributes of the complex object.

Are they really objects?
To this point, I've told you that Python deals only with object types, yet the examples don't really seem to have any objects. After all, where are the constructors? For the simple built-in data types, Python does a lot of the work for you. But the constructors are still there -- their names are identical to the name of the relevant data type -- and if you prefer, you can use them directly, as shown below:

Listing 11. Python constructors

Python is an amazingly simple, yet powerful language. The entry barrier is extremely low, especially for a programmer who has experience with a C-like language. This article introduced the Python programming language and the built-in data types: bool, int, long, float, and complex. If you haven't already done so, fire up a Python interpreter and try some of the ideas I've discussed. You'll be glad you did.


About the author
Robert J. Brunner is a research scientist at the National Center for Supercomputing Applications and an assistant professor of astronomy at the University of Illinois, Urbana-Champaign. He has published several books, as well as numerous articles and tutorials, on a range of topics.
想对作者说点什么? 我来说一句