Monday, August 25, 2014

Why Python is Slow: Looking Under the Hood

"It boils down to Python being a dynamically typed, interpreted language, where values are stored not in dense buffers but in scattered objects. And then I talk about how to get around this by using NumPy, SciPy, and related tools for vectorization of operations and calling into compiled code, and go on from there."

Full article: http://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/

Key differences between Python 2.7.x and Python 3.x

This article describe the main differences between Python 2 and 3.

From my perspective, this is the most important change of all:

Unicode

Python 2 has ASCII str() types, separate unicode(), but no byte type.
Now, in Python 3, we finally have Unicode (utf-8) strings, and 2 byte classes: byte and bytearrays.

Python 2

In [2]: print 'Python', python_version()
Python 2.7.6
In [3]: print type(unicode('this is like a python3 str type'))
<type 'unicode'>
In [4]: print type(b'byte type does not exist')
<type 'str'>
In [5]: print 'they are really' + b' the same'
they are really the same
In [7]: print type(bytearray(b'bytearray oddly does exist though'))
<type 'bytearray'>

Python 3

In [6]:
print('Python', python_version())
print('strings are now utf-8 \u03BCnico\u0394é!')
Python 3.4.1
strings are now utf-8 μnicoΔé!
In [8]:
print('Python', python_version(), end="")
print(' has', type(b' bytes for storing data'))
Python 3.4.1 has <class 'bytes'>
In [11]:
print('and Python', python_version(), end="")
print(' also has', type(bytearray(b'bytearrays')))
and Python 3.4.1 also has <class 'bytearray'>
In [13]:
'note that we cannot add a string' + b'bytes for data'
--------------------------------------------------------------------------- 
TypeError Traceback (most recent call last)
<ipython-input-13-d3e8942ccf81> in <module>()  
----> 1 'note that we cannot add a string' + b'bytes for data'

TypeError: Can't convert 'bytes' object to str implicitly
 
 
 
Full article: http://nbviewer.ipython.org/github/rasbt/python_reference/blob/master/tutorials/key_differences_between_python_2_and_3.ipynb 

Friday, August 22, 2014

Web Components: Is it the future?

Not saying this is the future, but unless this is really interesting.
They still have things to solve, but I would like to see this working on some big site.


Thursday, August 21, 2014

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

10 Most Common Python Mistakes

 Great article about most common mistakes in Python programing, sharing cause I really liked it..

I would like to mention the most common one unless from my perspective:

Common Mistake #1: Misusing expressions as defaults for function arguments

Python allows you to specify that a function argument is optional by providing a default value for it. While this is a great feature of the language, it can lead to some confusion when the default value is mutable. For example, consider this Python function definition:

>>> def foo(bar=[]): # bar is optional and defaults to [] if not specified
...    bar.append("baz") # but this line could be problematic
...    return bar
 
A common mistake is to think that the optional argument will be set to the specified default expression each time the function is called without supplying a value for the optional argument. In the above code, for example, one might expect that calling foo() repeatedly (i.e., without specifying a bar argument) would always return 'baz', since the assumption would be that each time foo() is called (without a bar argument specified) bar is set to [] (i.e., a new empty list).

But let’s look at what actually happens when you do this:

>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
>>> foo()
["baz", "baz", "baz"]
 
Huh? Why did it keep appending the default value of "baz" to an existing list each time foo() was called, rather than creating a new list each time?
The answer is that the default value for a function argument is only evaluated once, at the time that the function is defined. Thus, the bar argument is initialized to its default (i.e., an empty list) only when foo() is first defined, but then calls to foo() (i.e., without a bar argument specified) will continue to use the same list to which bar was originally initialized.

FYI, a common workaround for this is as follows:

>>> def foo(bar=None):
...    if bar is None:  # or if not bar:
...        bar = []
...    bar.append("baz")
...    return bar
...
>>> foo()
["baz"]
>>> foo()
["baz"]
>>> foo()
["baz"]


Full article:
http://www.toptal.com/python/top-10-mistakes-that-python-programmers-make