Posts Tagged ‘Python’

The good and bad about web2py

July 29th, 2010

a few months ago I was looking for a web development framework that is less painful and fun. Earlier I’ve been using web2py and I was partially satisfied of what it can do in a very short period of time. However, after I started to use web2py in production I was hit by the following facts that made me completely unhappy

Disadvantages of web2py

  • web2py doesn’t support unit testing, it supports doctests which is far from being optimal for a testing freak like me and is too limited in terms for the scope, you cannot really do the same level of tests you used to do in normal server side or desktop programs.
  • web2py does use Python which is my favorite scripting language so far and the one that I have been using for the last couple of years continuously. While Python is a great language it was used in a twisted way to design the framework, Python magic was all over the place, variables defined globally are allover, you cannot see real OO in the design, plus the code follows PEP-8 which I hate its do_blah_function style (lots of underscores). » Read more: The good and bad about web2py

Common Mistake about Python default parameter value

October 1st, 2009

I know it’s a little bit long title but didn’t find a better one :) It’s one of the common mistakes a python beginner does and even more experienced programmers can fall into the same mistake so I thought it might be useful if I illustrated that out here so you can know the concept.

you can easily fall into writing code that look like that:

def get_me_bad_list(arg1, myList=[]):
    myList.append(arg1)
    return myList

In [1]: get_me_bad_list(“hello”)
Out[1]: ['hello']

In [2]: get_me_bad_list(“world”)
Out[2]: ['hello', 'world']

Interesting, no?

The issue here is that the default value for function parameter is evaluated at function definition time (i.e, module import?) and as list objects are mutable they allow you change the value so you keep having the same default object for every function call and you modify it and return it back and even worse the caller can change it and it’ll reflect the list inside the function like the following

In [3]: x = get_me_bad_list(“Assalam”)

In[4]: x.append(“Alaykum”)

In[4]: get_me_bad_list(“Ya Shabab”)

Out[4]: ['hello', 'world', 'Assalam', 'Alaykum', 'Ya Shabab']

So, what’s the right way to do that? (if you are not doing that intentionally and you just want the plain default function parameters) that you define the initial value inside the body of the function (execution time)

def get_me_good_list(arg1, myList=None):
    myList = [] if myList is None else myList
    myList.append(arg1)
    return myList

In [1]: get_me_good_list(“hello”)
Out[1]: ['hello']

In [2]: get_me_good_list(“world”)
Out[2]: ['world']

and I’ll leave the rest of the tests to you, but generally the explanation is that everytime you call the function we create a new list (if you didn’t supply one explicitly) and that list is populated and returned so you won’t see any nasty behavior.

It’s interesting that you see that the deep you understand how the python interpreter scan and execute the code can really affect the way you fall into mistakes because if you are good enough then you will be somehow safe :)

Python recursion performance test

July 15th, 2009

That’s really shocking, I even tried several ways to optimize performance without touching the code and still performance sucks!

Fibonacci simple recursion solution takes 3 seconds to execute with C code and about 2 minutes in python!

Here is the code I used for the python version

def fib(x):
    if x == 0 or x == 1: return x
    return fib(x-1) + fib(x-2)

if you called fib(40) it will take about 2 minutes! the C code is exactly the same and it’s compiled with normal optmizations (-O0)

I compiled the python to pyc and used the pyc and still around 2 minutes (slightly less)

the impressive thing is that the dynamic programming solution works perfectly in no time, try this

def fib(x):
    t = [0, 1]
    for i in xrange(x):
        t.append(t[-1] + t[-2])
    return t[-2]
 

call it for fib(40) and see the performance gain.

the bottomline is that you shouldn’t use recursion in python.

If you have any suggestions to make this goes faster (I thought about trying stackless python here) I’m really happy to discuss them.