While working with Locust 1 recently, we ran into a situation where we had to dynamically override an attribute in a class in the Locust library so as to control what value it got assigned. After a lot of scratching our heads and reading the Python documentation, we came across the property function. We were able to use this to hack together a solution that ensures that every time an attribute is read, it returns the result of executing a method.

The following example demonstrates a stripped down version of this hack.

import random

class Foo(object):
    bar = random.random()

foo = Foo()

# Prints the value assigned when the Foo object is initialised.
print("Before override")

# Override
Foo.bar = property(lambda self: random.random())

print("After override")

This snippet when executed will output the following:

Before override
After override

It can be seen that before introducing the override, the value of the bar attribute is set when the class is initialised and as expected, it does not change how many ever times the attribute is read. However, after the override, the attribute is assigned a new value every time it is read.

How does this work?

The property() 2 function returns an attribute for any class. It allows the creation of Ruby’s attr_accessor 3 style attributes on classes so that one can write instance.attrib to read an attribute value and instance.attrib= to set an attribute value. What line 14 in the snippet does is to re-define the bar attribute to be a property whose getter is a lambda. Every time the bar attribute is read, the lambda gets executed.

A more comprehensive example of this can be found in my Python dojo repository on GitHub.

  1. Locust - a modern load testing framework. [return]
  2. Python’s built-in functions - property. [return]
  3. Ruby’s attr_accessor method. [return]

If you have questions or comments about this blog post, you can get in touch with me on Twitter @sdqali.

If you liked this post, you'll also like...