Tag Archives: Python 201

Python 201: What are descriptors?

Descriptors were introduced to Python way back in version 2.2. They provide the developer with the ability to add managed attributes to objects. The methods needed to create a descriptor are __get__, __set__ and __delete__. If you define any of these methods, then you have created a descriptor.

The idea behind the descriptor is to get, set or delete attributes from your object’s dictionary. When you access a class attribute, this starts the lookup chain. Should the looked up value be an object with one of our descriptor methods defined, then the descriptor method will be invoked.

Descriptors power a lot of the magic of Python’s internals. They are what make properties, methods and even the super function work. They are also used to implement the new style classes that were also introduced in Python 2.2.


The Descriptor Protocol

The protocol to create a descriptor is really quite easy. You only need to define one or more of the following:

  • __get__(self, obj, type=None), returns value
  • __set__(self, obj, value), returns None
  • __delete__(self, obj), returns None

Once you’ve defined at least one, you have created a descriptor. If you can you define both __get__ and __set__, you will have created a data descriptor. A descriptor with only __get__() defined are known as non-data descriptors and are usually used for methods. The reason for this distinction in descriptor types is that if an instance’s dictionary happens to have a data descriptor, the descriptor will take precedence during the lookup. If the instance’s dictionary has an entry that matches up with a non-data descriptor, then the dictionary’s own entry will take precedence over the descriptor.

You can also create a read-only descriptor if you define both __get__ and __set__, but raise an AttributeError when the __set__ method is called.

Continue reading Python 201: What are descriptors?

Python 201: An Intro to itertools

Python provides a great module for creating your own iterators. The module I am referring to is **itertools**. The tools provided by itertools are fast and memory efficient. You will be able to take these building blocks to create your own specialized iterators that can be used for efficient looping. In this chapter, we will be looking at examples of each building block so that by the end you will understand how to use them for your own code bases.

Let’s get started by looking at some infinite iterators!

Continue reading Python 201: An Intro to itertools

Python 201 – The handy defaultdict

The collections module has another handy tool called defaultdict. The defaultdict is a subclass of Python’s dict that accepts a default_factory as its primary argument. The default_factory is usually a Python type, such as int or list, but you can also use a function or a lambda too. Let’s start by creating a regular Python dictionary that counts the number of times each word is used in a sentence:

sentence = "The red for jumped over the fence and ran to the zoo for food"
words = sentence.split(' ')
 
reg_dict = {}
for word in words:
    if word in reg_dict:
        reg_dict[word] += 1
    else:
        reg_dict[word] = 1
 
print(reg_dict)

If you run this code, you should see output that is similar to the following:

{'The': 1,
 'and': 1,
 'fence': 1,
 'food': 1,
 'for': 2,
 'jumped': 1,
 'over': 1,
 'ran': 1,
 'red': 1,
 'the': 2,
 'to': 1,
 'zoo': 1}

Now let’s try doing the same thing with defaultdict!

from collections import defaultdict
 
 
sentence = "The red for jumped over the fence and ran to the zoo for food"
words = sentence.split(' ')
 
d = defaultdict(int)
for word in words:
    d[word] += 1
 
print(d)

You will notice right away that the code is much simpler. The defaultdict will automatically assign zero as the value to any key it doesn’t already have in it. We add one so it makes more sense and it will also increment if the word appears multiple times in the sentence.

defaultdict(<class 'int'>,
            {'The': 1,
             'and': 1,
             'fence': 1,
             'food': 1,
             'for': 2,
             'jumped': 1,
             'over': 1,
             'ran': 1,
             'red': 1,
             'the': 2,
             'to': 1,
             'zoo': 1})
</class>

Now let’s try using a Python list type as our default factory. We’ll start off with a regular dictionary first, as before.

Continue reading Python 201 – The handy defaultdict

Python 201 Book Outline

Over the weekend, I spent some time rearranging ideas for my latest book such that I have have four specific sections of the book. Here they are:

Part I – Intermediate Modules

  • Chapter 1 – The argparse module
  • Chapter 2 – The collections module
  • Chapter 3 – The contextlib module (Context Managers)
  • Chapter 4 – The functools module (Function overloading, caching, etc)
  • Chapter 5 – All about imports
  • Chapter 6 – The importlib module
  • Chapter 7 – The itertools module
  • Chapter 8 – The re module (An Intro to Regex in Python)
  • Chapter 9 – The typing module (Type Hinting)

Part II – Odds and Ends

  • Chapter 10 – generators / iterators
  • Chapter 11 – map, filter, reduce
  • Chapter 12 – unicode
  • Chapter 13 – benchmarking
  • Chapter 14 – encryption
  • Chapter 15 – Connecting to databases

Part III – Web

  • Chapter 16 – Web scraping
  • Chapter 17 – Working with web APIs
  • Chapter 18 – ftplib
  • Chapter 19 – urllib / httplib (client / server)

Part IV – Testing

  • Chapter 20 – Doctest
  • Chapter 21 – unittest
  • Chapter 22 – mock
  • Chapter 23 – coverage.py

I want to note that these are just the topics that will absolutely be included. I may add others. I will also be adding others should I reach my stretch goal. If you’re interested in getting early access to the book or just want to support the blog, you can do so at my Kickstarter for Python 201!