Book Image

The Python Apprentice

By : Robert Smallshire, Austin Bingham
Book Image

The Python Apprentice

By: Robert Smallshire, Austin Bingham

Overview of this book

Experienced programmers want to know how to enhance their craft and we want to help them start as apprentices with Python. We know that before mastering Python you need to learn the culture and the tools to become a productive member of any Python project. Our goal with this book is to give you a practical and thorough introduction to Python programming, providing you with the insight and technical craftsmanship you need to be a productive member of any Python project. Python is a big language, and it’s not our intention with this book to cover everything there is to know. We just want to make sure that you, as the developer, know the tools, basic idioms and of course the ins and outs of the language, the standard library and other modules to be able to jump into most projects.
Table of Contents (21 chapters)
Title Page
Credits
About the Authors
www.PacktPub.com
Customer Feedback
Preface
12
Afterword – Just the Beginning

Getting help()


But how can we find out what other functions are available in the math module?

The REPL has a special function help() which can retrieve any embedded documentation from objects for which documentation has been provided, such as standard library modules.

To get help, simply type help at the prompt:

>>> help
Type help() for interactive help, or help(object) for help about object.

We'll leave you to explore the first form — for interactive help — in your own time. Here we'll go for the second option and pass the math module as the object for which we want help:

>>> help(math)
Help on module math:

NAME
 math

MODULE REFERENCE
       http://docs.python.org/3.3/library/math

   The following documentation is automatically generated from the    
   Python source files. It may be incomplete, incorrect or include 
   features that are considered implementation detail and may vary 
   between Python implementations. When in doubt, consult the module 
   reference at the location listed above.

DESCRIPTION
 This module is always available. It provides access to the
 mathematical functions defined by the C standard.

FUNCTIONS
 acos(...)
 acos(x)

 Return the arc cosine (measured in radians) of x.

You can use the space-bar to page through the help, and if you're on Mac or Linux use the arrow keys to scroll up and down.

Browsing through the functions, you'll can see that there's a math function, factorial, for computing factorials. Press Q to exit the help browser, and return us to the Python REPL.

Now practice using help() to request specific help on the factorial function:

>>> help(math.factorial)
Help on built-in function factorial in module math:

factorial(...)
 factorial(x) -> Integral

 Find x!. Raise a ValueError if x is negative or non-integral.

Press Q to return to the REPL.

Let's use factorial() a bit. The function accepts an integer argument and return an integer value:

>>> math.factorial(5)
120
>>> math.factorial(6)
720

Notice how we need to qualify the function name with the module namespace. This is generally good practice, as it makes it abundantly clear where the function is coming from. That said, it can result in code that is excessively verbose.

Counting fruit with math.factorial()

Let's use factorials to compute how many ways there are to draw three fruit from a set of five fruit using some math we learned in school:

>>> n = 5
>>> k = 3
>>> math.factorial(n) / (math.factorial(k) * math.factorial(n - k))
10.0

This simple expression is quite verbose with all those references to the math module. The Python import statement has an alternative form that allows us to bring a specific function from a module into the current namespace by using the from keyword:

>>> from math import factorial
>>> factorial(n) / (factorial(k) * factorial(n - k))
10.0

This is a good improvement, but is still a little long-winded for such a simple expression.

A third form of the import statement allows us to rename the imported function. This can be useful for reasons of readability, or to avoid a namespace clash. Useful as it is, though, we recommend that this feature be used infrequently and judiciously:

>>> from math import factorial as fac
>>> fac(n) / (fac(k) * fac(n - k))
10.0

 

Different types of numbers

Remember that when we used factorial() alone it returned an integer. But our more complex expression above for calculating combinations is producing a floating point number. This is because we've used /, Python's floating-point division operator. Since we know our operation will only ever return integral results, we can improve our expression by using //, Python’s integer division operator:

>>> from math import factorial as fac
>>> fac(n) // (fac(k) * fac(n - k))
10

What's notable is that many other programming languages would fail on the above expression for even moderate values of n. In most programming languages, regular garden variety signed integers can only store values less than {ParseError: KaTeX parse error: Expected 'EOF', got '}' at position 1: }̲2\times10^{31}}:

>>> 2**31 - 1
2147483647

However, factorials grow so fast that the largest factorial you can fit into a 32-bit signed integer is 12! since 13! is too large:

>>> fac(13)
6227020800

In most widely used programming languages you would need either more complex code or more sophisticated mathematics merely to compute how many ways there are to draw 3 fruits from a set of 13!. Python encounters no such problems and can compute with arbitrarily large integers, limited only by the memory in your computer. To demonstrate this further, let's try the larger problem of computing how many different pairs of fruit we can pick from 100 different fruits (assuming we can lay our hands on so many fruit!):

>>> n = 100
>>> k = 2
>>> fac(n) // (fac(k) * fac(n - k))
4950

Just to emphasize how large the size of the first term of that expression is, calculate 100! on it's own:

>>> fac(n)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

This number is vastly larger even than the number of atoms in the known universe, with an awful lot of digits. If, like us, you're curious to know exactly how many digits, we can convert our integer to a text string and count the number of characters in it like this:

>>> len(str(fac(n)))
158

That's definitely a lot of digits. And a lot of fruit. It also starts to show how Python's different data types — in this case, integers, floating point numbers, and text strings — work together in natural ways. In the next section we'll build on this experience and look at integers, strings, and other built-in types in more detail.