Friday, February 12, 2016

Examples of method chaining in Python


By Vasudev Ram



The topic of method chaining came up during a training program I was conducting. So I thought of writing a post about it, with a couple of examples.

Method chaining is a technique (in object-oriented languages) for making multiple method calls on the same object, without using the object reference more than once. Example:

Let's say we have a class Foo that contains two methods, bar and baz.
We create an instance of the class Foo:
foo = Foo()
Without method chaining, to call both bar and baz in turn, on the object foo, we would do this:
# Fragment 1
foo.bar() # Call method bar() on object foo.
foo.baz() # Call method baz() on object foo.
# With method chaining, we can this:
# Fragment 2
Chain calls to methods bar() and baz() on object foo.
foo.bar().baz()
So you can loosely think of method chaining as the object-oriented version of nested function calls in procedural programming, where, instead of this:
# Fragment 3
temp1 = foo(args)
result = bar(temp)
you would do this:
# Fragment 4
result = bar(foo(args))
We use nested function calls all the time in procedural programming, and even in the procedural sections of code that occur in a Python program that uses OOP. We can do the latter because Python supports both styles (procedural and object-oriented) at the same time, even in the same program; Guido be thanked for that :)

The above was my informal description of method chaining. For more details, refer to this Wikipedia article, which includes examples in various programming languages. The article also makes a distinction between method chaining and method cascading, and according to it, what I call method chaining here (involving returning the self reference) is really method cascading. Are you confused enough? :) Kidding, the difference is not really complex.

One advantage of method chaining is that it reduces the number of times you have to use the name of the object: only once in Fragment 2 above, vs. twice in Fragment 1; and this difference will increase when there are more method calls on the same object. Thereby, it also slightly reduces the amount of code one has to read, understand, test, debug and maintain, overall. Not major benefits, but can be useful.

Note: One limitation of method chaining is that it can only be used on methods which do not need to return any other meaningful value, such as a count of lines modified, words found, records deleted, etc. (which some methods need to do), because you need to return the self object. Even the fact that Python (and some other languages) support returning multiple values from a return statement, may not solve this. (There could be some workaround for this, but it might look awkward, is my guess.)

Simple method chaining can be implemented easily in Python.
Here is one way of doing it:
# foo_bar_baz.py
# Demonstrates method chaining.

class Foo(object):
    def bar(self):
        print "Method Foo.bar called"
        return self

    def baz(self):
        print "Method Foo.baz called"
        return self

foo = Foo()
# Saving return value in foo2 not needed;
# doing to use with id function below.
foo2 = foo.bar().baz()
print

# We can also do it like this, if we don't want 
# to save the object foo for later use:
Foo().bar().baz()
print

# Show that the original foo's id and the returned foo2's id 
# are the same, i.e. they are the same object:
print " id(foo):", id(foo)
print "id(foo2):", id(foo2)
Here is the output of running the above program:
$ python foo_bar_baz.py
Method Foo.bar called
Method Foo.baz called

Method Foo.bar called
Method Foo.baz called

 id(foo): 34478576
id(foo2): 34478576
While writing this post, I also searched for more information, and found a couple of interesting links on method chaining:

Stack Overflow question on method chaining in Python, with some other approaches.

ActiveState Code Python recipe on method chaining

I also wrote another small program, string_processor.py, which shows a somewhat more realistic situation in which one might want to use method chaining:
'''
Program: string_processor.py
Demo of method chaining in Python.
By: Vasudev Ram - 
http://jugad2.blogspot.in/p/about-vasudev-ram.html
Copyright 2016 Vasudev Ram
'''

import copy

class StringProcessor(object):
    '''
    A class to process strings in various ways.
    '''
    def __init__(self, st):
        '''Pass a string for st'''
        self._st = st

    def lowercase(self):
        '''Make lowercase'''
        self._st = self._st.lower()
        return self

    def uppercase(self):
        '''Make uppercase'''
        self._st = self._st.upper()
        return self

    def capitalize(self):
        '''Make first char capital (if letter); make other letters lower'''
        self._st = self._st.capitalize()
        return self

    def delspace(self):
        '''Delete spaces'''
        self._st = self._st.replace(' ', '')
        return self

    def rep(self):
        '''Like Python's repr'''
        return self._st

    def dup(self):
        '''Duplicate the object'''
        return copy.deepcopy(self)

def process_string(s):
    print
    sp = StringProcessor(s)
    print 'Original:', sp.rep()
    print 'After uppercase:', sp.dup().uppercase().rep()
    print 'After lowercase:', sp.dup().lowercase().rep()
    print 'After uppercase then capitalize:', sp.dup().uppercase().\
    capitalize().rep()
    print 'After delspace:', sp.dup().delspace().rep()

def main():
    print "Demo of method chaining in Python:"
    # Use extra spaces between words to show effect of delspace.
    process_string('hOWz  It     GoInG?')
    process_string('The      QUIck   brOWn         fOx')

main()
Does adding the rep() and dup() make it more methodical? :)

Here is the output of running it:
$ python string_processor.py
Demo of method chaining in Python:

Original: hOWz  It     GoInG?
After uppercase: HOWZ  IT     GOING?
After lowercase: howz  it     going?
After uppercase then capitalize: Howz  it     going?
After delspace: hOWzItGoInG?

Original: The      QUIck   brOWn         fOx
After uppercase: THE      QUICK   BROWN         FOX
After lowercase: the      quick   brown         fox
After uppercase then capitalize: The      quick   brown         fox
After delspace: TheQUIckbrOWnfOx
So, to sum up, we can see that method chaining has its uses, though overdoing it is probably not a good idea.

Finally, and related, via the Stack Overflow article linked above, I came across this post about Collection Pipelines on Martin Fowler's site.

Reading that article made me realize that nested function calls, method chaining and Unix command pipelines are all related concepts. You may also find these other posts by me of interest:

fmap(), "inverse" of Python map() function

Generate PDF from a Python-controlled Unix pipeline

- Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes


Thursday, February 11, 2016

Video: Rails creator DHH interview by Jason Calacanis on This Week in Startups

By Vasudev Ram

Saw this video via a Disqus comment:

Video: Rails creator DHH interviewed by Jason Calacanis on This Week in Startups

Started watching, seems interesting. Might want to skip some of the start where a show viewer calls in, to get to the main story.

At some part it is like the interviewee is interviewing the interviewer. Video also embedded below.



- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes


Wednesday, February 3, 2016

Using Python's trace module to understand the flow of programs (from many angles)

By Vasudev Ram


Some time back, I had written this post:

Python's trace module and chained decorators

in which I had briefly described use of the Python standard library's trace module to help us understand and debug Python programs. In that post I showed a small program with 3 chained decorators. The trace module was used to trace the execution of the decorators and the functions that they decorated.

The trace output in that post also showed the difference between function definition and function execution, both of which occur at run time in Python, since it is a dynamic language.

In this post, I'm going to use the trace module in a few other ways.

Here is a small program in which we will use the trace module.

(Note that I said "in which", not "on which", because I am going to invoke the trace module as a library from within this program, and tell it to start tracing from a specific function call, unlike in my previous post (linked above), in which I used the trace module as though it was a program itself, by using the "python -m" option, to trace my own program containing those decorators.)
# This is a program to show some basic usage of the trace module 
# from the Python standard library.
# Author: Vasudev Ram - 
# http://jugad2.blogspot.in/p/about-vasudev-ram.html
# Copyright 2016 Vasudev Ram

def fa():
    fb()

def fb():
    fc()

def fc():
    fd(5)

def fd(n):
    if n <= 1:
        return
    else:
        fd(n - 1)

import trace

tracer = trace.Trace(
    count=0, trace=0, countfuncs=0, countcallers=1, 
)

tracer.run('fa()')
r = tracer.results()
r.write_results(show_missing=True, coverdir=".")
In this program, I have a function fa calling fb which calls fc which calls fd. Function fd also calls itself recursively, with a termination condition so the recursion is not infinite.

Note that the program contains all the three main programming constructs: sequential execution of statements, conditional execution and iteration (via the recursive call in function fd).

From the Python documentation, the trace.Trace() constructor has the following (partial) signature:

class trace.Trace(count=1, trace=1, countfuncs=0, countcallers=0, ...)

where I have used ellipsis (...) to represent the remaining arguments, which I do not pass. (See the docs (linked above, near top of post) for the full signature and the meaning of all the arguments. The ones I use are explained below.)

As for what those arguments do, again, from the docs:

Create an object to trace execution of a single statement or expression. All parameters are optional. count enables counting of line numbers. trace enables line execution tracing. countfuncs enables listing of the functions called during the run. countcallers enables call relationship tracking.

I ran the program simple_prog.py 4 times. Each time I passed a different combination of argument values to trace.Trace() - with only one argument set to 1 each time, and all the others set to 0 in that run. And each time I redirected the resulting trace output to an output file, except for the first run, in which Python created the output in the file simple_prog.cover (since the program being traced is named simple_prog.py.

The lines below show the sets of arguments passed, and the corresponding output file names for the trace output. (I will show the contents of each output file later, below.)

arg set 1: count=1, trace=0, countfuncs=0, countcallers=0, output: simple_prog.cover

arg set 2: count=0, trace=1, countfuncs=0, countcallers=0, output: run_2.txt

arg set 3: count=0, trace=0, countfuncs=1, countcallers=0, output: run_3.txt

arg set 4: count=0, trace=0, countfuncs=0, countcallers=1, output: run_4.txt

Notice that in each of the arg sets, only one flag is set.

I ran the program this time with just:

python simple_prog.py

since the tracing is started from within the program, unlike in my previous post (linked above) in which I started the tracing like this:

python -m trace -t test_chained_decorators.py

Here is the output for the 1st run, simple_prog.cover:

# This is a program to show some basic usage of the trace module 
       # from the Python standard library.
       # Author: Vasudev Ram - 
       # http://jugad2.blogspot.in/p/about-vasudev-ram.html
       # Copyright 2016 Vasudev Ram
       
>>>>>> def fa():
    1:     fb()
       
>>>>>> def fb():
    1:     fc()
       
>>>>>> def fc():
    1:     fd(5)
       
>>>>>> def fd(n):
    5:     if n <= 1:
    1:         return
           else:
    4:         fd(n - 1)
       
>>>>>> import trace
       
>>>>>> tracer = trace.Trace(
>>>>>>     count=1, trace=0, countfuncs=0, countcallers=0, 
       )
       
>>>>>> tracer.run('fa()') # This line starts the tracing process.
>>>>>> r = tracer.results()
>>>>>> r.write_results(show_missing=True, coverdir=".")
You can see that the output includes the counts of the number of times lines of code are called. Notice that there are no line counts for the def lines, presumably because function definitions are only supposed to be done once (by definition, ha ha), so it would not make sense to show it, and might even be confusing.

Here is the output for the 2nd run, run_2.txt:

--- modulename: simple_prog, funcname: <module>
<string>(1):   --- modulename: simple_prog, funcname: fa
simple_prog.py(6):     fb()
 --- modulename: simple_prog, funcname: fb
simple_prog.py(9):     fc()
 --- modulename: simple_prog, funcname: fc
simple_prog.py(12):     fd(5)
 --- modulename: simple_prog, funcname: fd
simple_prog.py(15):     if n <= 1:
simple_prog.py(18):         fd(n - 1)
 --- modulename: simple_prog, funcname: fd
simple_prog.py(15):     if n <= 1:
simple_prog.py(18):         fd(n - 1)
 --- modulename: simple_prog, funcname: fd
simple_prog.py(15):     if n <= 1:
simple_prog.py(18):         fd(n - 1)
 --- modulename: simple_prog, funcname: fd
simple_prog.py(15):     if n <= 1:
simple_prog.py(18):         fd(n - 1)
 --- modulename: simple_prog, funcname: fd
simple_prog.py(15):     if n <= 1:
simple_prog.py(16):         return
 --- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)
Since the trace flag is set, we get line execution tracing. And due to that, there are 5 entries for function fd, since there are 5 calls to it (of which 4 are recursive).

Here is the output for the 3rd run, run_3.txt:

functions called:
filename: <string>, modulename: <string>, funcname: <module>
filename: D:\Anaconda-2.1.0-64\lib\trace.py, modulename: trace, funcname: _unsettrace
filename: simple_prog.py, modulename: simple_prog, funcname: fa
filename: simple_prog.py, modulename: simple_prog, funcname: fb
filename: simple_prog.py, modulename: simple_prog, funcname: fc
filename: simple_prog.py, modulename: simple_prog, funcname: fd
Since the countfuncs flag is set, it shows the functions called during the run of the program.

Here is the output for the 4th run, run_4.txt:

calling relationships:

*** <string> ***
  --> simple_prog.py
    <string>.<module> -> simple_prog.fa

*** D:\Anaconda-2.1.0-64\lib\trace.py ***
  --> <string>
    trace.Trace.runctx -> <string>.<module>
    trace.Trace.runctx -> trace._unsettrace

*** simple_prog.py ***
    simple_prog.fa -> simple_prog.fb
    simple_prog.fb -> simple_prog.fc
    simple_prog.fc -> simple_prog.fd
    simple_prog.fd -> simple_prog.fd
Since the countcallers flag is set, it shows the function call tree during the run of the program, i.e. what function called what other function(s). The last line shows the recursive call to fd.

So we can see, overall, that those four flags to trace.Trace(), allowed us to get insight into the behaviour of the program, from various angles or perspectives. This makes the trace module a useful tool for debugging and for understanding code that we have to work on.

- Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes

Sunday, January 24, 2016

RIP Ed Yourdon


https://en.wikipedia.org/wiki/Edward_Yourdon

http://yourdon.com/about/

" According to the December 1999 issue of Crosstalk: The Journal of Defense Software Engineering, Ed Yourdon is one of the ten most influential men and women in the software field."

He had a lot of influence on the Indian software industry too, from its early days.

Tuesday, January 19, 2016

Simple drawing program with Python turtle graphics

By Vasudev Ram


Image attribution: Claudio Giovenzana www.longwalk.it

Some time back I had written a post with a simple turtle graphics program in Python:

(The history of turtle graphics is of interest, including the early years, when they used actual robots for the turtles, which were controlled by programs). The Wikipedia page in the link above has the details.)

Here is the post I wrote earlier:

Python, meet Turtle

Python has support for turtle graphics in the standard library.

Today I wrote a different kind of turtle graphics program: a simple drawing program that allows you to interactively draw figures using a few keys on the keyboard.

The program is a first version, so is not polished. But it works, as far as I tested it.

You can use the following keys to control the turtle and draw:

- up arrow to move forward
- down arrow to move backward
- left arrow to turn left 45 degrees
- right arrow to turn right 45 degrees
- h or H key to move the turtle to its home position (center of screen, heading east)
- c or C key to clear the screen
- q or Q to quit the program

Note: If you do Clear and then Home, and if your turtle had been away from the home position when you did the Clear, the screen will get cleared, but then the Home action will draw a line from where the turtle just was to its (new) home position. If that happens, just press C again to clear the screen of that line.
The better way is to do Home first and then Clear.

Here is the code for the program:
# Program to do drawing using Python turtle graphics.
# turtle_drawing.py v0.1
# Author: Vasudev Ram
# http://jugad2.blogspot.in/p/about-vasudev-ram.html
# Copyright (C) 2016 Vasudev Ram.

import turtle

# Create and set up screen and turtle.

t = turtle
# May need to tweak dimensions below for your screen.
t.setup(600, 600)
t.Screen()
t.title("Turtle Drawing Program - by Vasudev Ram")
t.showturtle()

# Set movement step and turning angle.
step = 160
angle = 45

def forward():
    '''Move forward step positions.'''
    print "forward", step
    t.forward(step)

def back():
    '''Move back step positions.'''
    print "back", step
    t.back(step)

def left():
    '''Turn left by angle degrees.'''
    print "left", angle
    t.left(angle)

def right():
    '''Turn right by angle degrees.'''
    print "right", angle
    t.right(angle)

def home():
    '''Go to turtle home.'''
    print "home"
    t.home()

def clear():
    '''Clear drawing.'''
    print "clear"
    t.clear()

def quit():
    print "quit"
    t.bye()

t.onkey(forward, "Up")
t.onkey(left, "Left")
t.onkey(right, "Right")
t.onkey(back, "Down")
t.onkey(home, "h")
t.onkey(home, "H")
t.onkey(clear, "c")
t.onkey(clear, "C")
t.onkey(quit, "q")
t.onkey(quit, "Q")

t.listen()
t.mainloop()
Support for more turtle actions (see the Python turtle module's docs linked above) can be added, for many of them on the same pattern as the existing functions, without changing the overall structure of the program. Some others may require changes to the design, which is very simple as of now. (I applied the principle Do The Simplest Thing That Could Possibly Work.)

Also, a point to note: many of the capabilities of the turtle module are available in both procedural and object-oriented versions. Here, to keep it simple, I've used the procedural style.

Here are a few screenshots of drawings I created by running and using this program:

A diamond (just a square tilted):


A square:


A figure made out of squares:


The image at the top of the post is of Olive ridley sea turtles.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes