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.
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
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.