Tag Archives: Python

Why no operators ++ and — in Python

Python doesn’t have operators ++ and -- like most C-based languages. Instead you need to use += and -=.

x += y
x -= z

These are shortcuts for the following assignments:

x = x + y
x = x - z

The reason is pretty obvious when you think about it – Python variables are immutable, so it would be impossible to have operators that modify them.

Getting the Python version

You can get the Python version with sys.version:

import sys
print(sys.version)
'3.4.3 (default, Oct 14 2015, 20:28:29) \n[GCC 4.8.4]'

However, rather than checking the version it’s much simpler and more Pythonic to try to use a version-dependent function and handle failure if it isn’t there.

Calling a top-level function that doesn’t exist will raise a NameError:

try:
    might_exist()
except NameError as err:
    # Do something else instead

While calling a module-level function that doesn’t exist will raise an AttributeError

try:
    maybe_module.might_exist()
except AttributeError as err:
    pass
    # Do something else instead

Counting the items in a list in Python

To count the number of a single item in a list, use the count() method:

from random import randint

dishes = ['spam', 'eggs', 'ham']
# Fill a list with 100 randomly selected dishes
orders = [dishes[randint(0, 2)] for i in range(1, 101)]
# Print the count of spam orders
print("spam: {0}".format(orders.count('spam')))
spam: 31

To get the counts of all items, use a collections.Counter

from collections import Counter

counter = Counter(orders)
print(counter)
Counter({'ham': 37, 'eggs': 32, 'spam': 31})

Difference between lists and tuples in Python

Lists and tuples in Python are both sequence types, and share a number of operations common to all sequence types:

  • in
  • +
  • *
  • slices
  • len()
  • min()
  • max()
  • index()
  • count()

However they are quite different in purpose and they way they are most commonly used:

  • Lists are mutable, and are generally used to store homogeneous objects (objects of the same type), which are accessed by iteration
  • Tuples are immutable, and are generally used to store heterogeneous objects, which are accessed by unpacking or indexing

This makes tuples more like lightweight objects, which is how they are often used. The namedtuple type takes this further by allowing indexing by named attributes.

Environment variables in Python

To get an variable, retrieve if from os.environ

    print(os.environ['HOME'])

It’s just like a dictionary, so you can print all of the entries:

    print(os.environ)

Just like a dictionary, the get() method will return None if the requested key isn’t present, so it never raises an KeyError, and can take a default value:

    print(os.environ.get('SPAM', 'EGGS'))

The os.getenv()` function behaves exactly the same way:

    print(os.getenv('SPAM', 'EGGS'))

is and == in Python

The is keyword tests whether two variables point to the same object. In other words this code:

a is b

Tests whether:

a.id() == b.id()

The == operator tests whether two objects have the same value. The meaning of this depends upon the type of the object.
It is defined in the obvious way for built-in types.

You can make your own types comparable with == by implementing __eq__():

class C(object):
    def __init__(self, val):
        self.val = val

    def __eq__(self, other):
        return self.val == other.val

c = C('spam')
d = C('spam')
print c == d
True

Note that because Python will cache and reuse object instances, two different objects that compare equal with == may also compare equal with is, but this should not be relied upon.

Mixins in Python

A mixin is a class which is used as an additional base class and adds the implementation of a feature, mixing it into the derived class. This allows derived classes to be assembled from components, adding only those features they require.

A good example of mixins is Werkzeug’s Request/Response Wrapper Mixins.

A typical Werkzeug application starts by taking the WSGI environment and constructs a Request object out of it:

def application(environ, start_response):
    request = Request(environ)

The Request class is often a user-defined class derived from werkzeug.wrappers.BaseRequest. This is a bare-bones class that does not provide features like E-Tags and cache control. In order for implementors to be able to add those features to their class, Werkzeug provides a number of mixins for HTTP features:

  • AcceptMixin for accept header parsing
  • ETagRequestMixin for etag and cache control handling
  • UserAgentMixin for user agent introspection
  • AuthorizationMixin for http auth handling
  • CommonRequestDescriptorsMixin for common headers

Implementors add one or more of these classes to the derivation list of their class to mix in the features they want:

from werkzeug.wrappers import AcceptMixin, BaseRequest

class Request(BaseRequest, AcceptMixin):
    pass

The implementor can then access attributes of the AcceptMixin from the Request class

mimetypes = request.accept_mimetypes

If this wasn’t done using mixins, it would be necessary to explicitly aggregate an object to implement the Accept headers when the Request object was constructed, something like this:

class Request(BaseRequest):
    def __init__(self):
        self.acceptor = AcceptComponent() # Not a real class

And then it would need to be accessed indirectly, something like this:

mimetypes = request.acceptor.accept_mimetypes # Not real code

So you can see that a mixin has simplified the construction and use of the class.

Two properties of mixins are:

  • By their very nature mixins are useless on their own – their sole purpose is to be mixed into other classes
  • They are tightly coupled to the classes into which they can be mixed in, since they must have intimate knowledge of them in order to be able to do anything useful