Style remarks
Some minor remarks about your style:
- Use 4 spaces for indentation
- Do not use camelCase for function names. Prefer underscores. A better name would be approximate_pi.
- Insert more empty lines, in particular 2 empty lines after the import statement.
- Spaces around operators and between function arguments.
- Avoid single letter variable names as much as you can. When dealing with mathematical problems it's not always easy to do, so it's okay to keep them. However avoid upper cases, unless you have reasons not to.
Look at how style can make your code more readable.
from fractions import Fraction
def approximate_pi(n):
listx = []
for i in xrange(4, n+1):
if i % 2 == 0:
listx.append(Fraction(i, i-1))
listx.append(Fraction(i, i+1))
listx.append(Fraction(2, 3))
return 4 * reduce(lambda x, y: float(x) * float(y), map(float, listx))
To understand better why style is such a big deal in the Python community, and how you should format your code, you should
read PEP8.
No need for a list
The problem with your code is that you're building a useless list. This can be costly if you want to run it on big numbers, affecting both memory consumption and performance.
You can solve the problem with a generator.
from fractions import Fraction
from operator import mul
def approximate_pi_generator(n):
yield Fraction(2, 3)
for i in xrange(4, n+1):
if i % 2 == 0:
yield Fraction(i, i-1)
yield Fraction(i, i+1)
def approximate_pi(n):
return 4 * reduce(mul, map(float, approximate_pi_generator(n)))
If you don't really understand generators, or how the
yield keyword behaves, you should
read this StackOverflow answer that does a great job at explaining them.
No need for a container
You don't even need to hold all these fraction in one place. You can multiply the Fractions on the fly.
from fractions import Fraction
def approximate_pi(n):
pi = float(Fraction(2, 3))
for i in xrange(4, n+1):
if i % 2 == 0:
pi *= Fraction(i, i-1)
pi *= Fraction(i, i+1)
return 4 * pi
Notice that I just explicitly transform the first element into a float. All the subsequent Fraction objects are automatically coerced into floats by Python itself.
Note on functional programming
While
map,
lambda and
reduce are fun, you should avoid using them when you can. Notice how the last code I write is more readable and quickly understandable.
You can read more about Guido's dislike of functional programming features in these links: