Getting started with Python (part 2)

In this tutorial, we’ll discuss learning Python from a C style language developer’s perspective.

C languages are, by design, very strict. You either do it their way, or your code won’t compile.

Python is the polar opposite of C languages. It takes a “we’re all consenting adults here” attitude, and let’s you do pretty much whatever you want.

Python is also built for speed. Not speed of execution, but speed of coding. It’s a great language if you want to throw a script together in a half hour.

We’re all consenting adults here

In most C style languages, classes allow you to “hide” information from people who consume the class. Hiding data and methods that shouldn’t be used by consumers of the class is encouraged.

Python isn’t really designed to hide methods or variables from other classes. It offers limited support for “private” class data, but it’s still possible (with a little leg work) to access it from another class.

I’m not sure if I like the lack of support for hiding certain things from consumers of my classes, but I like that I’ll always be able to poke around with the debugger into any class I need to.

Python is not strongly typed, nor do you have to define variables before you use them. This makes coding a little faster, but also introduces a problem for IDEs, which we’ll explore in a minute.

What’s really nice is you can do this:

a = "string";
a = 5;

Even better (although, not that useful):

a = ["string", 5, Foo()]

The above code creates a list with a string, an int, and an object.

Remember that problem I talked about? Here it is: If a code completion system doesn’t know what type a variable is, it can’t provide a list of methods, or call tips. A workaround is to make object method calls in the following form (we’ll call it form 1)

Foo.Bar(obj, param1, param2)

Personally, I’d just use that to figure out the method, then I’d change it back to (we’ll call it form 2):

obj.Bar(param1, param2)

Class methods have to follow an important convention. The convention is:

class Foo:
    def Bar(self, param1, param2):
        pass

Most developers will be thinking: “What the [word of choice here]? He just called a method that takes three args with three args, and then with two.”

The reason that I was able to do that is that I used the convention for class methods. self is the same as this in C++ and C# with one key exception. In order to access it, you MUST declare it as a parameter for your method, otherwise your function will be considered a regular function.

Apparently, Python coverts form 2 to form 1 when your code is run.

Here’s an interesting page I found about Python’s “self”.

Here’s a slice

Python has a really interesting thing called slices. Basically, slices provide a convenient way to reference a part of a collection. Technically a string is a “collection” of characters.

Slices are like array notation, with a second subscript attached by a colon.

a = ['abc', 'test2', 'test3']
a[0:2]

# Outputs ['abc', 'test2']

The second subscript defines the end position in the collection to stop printing items. Basically, it will go from the first index, until the current index is equal to the last index.

If we looked at it with a for loop (we’ll use the a variable from the previous snippet):

template<typename T>
T Operation(firstIndex, secondIndex)
{
    T item = new T();

    for (int i = firstIndex; i < secondIndex; i++)
        item.add(a[i]);

    return item;
}

One thing to keep in mind is that the type that gets returned from a slice operation is the same as object that you performed the slice on (which I tried to illustrate by showing the template function). What that means is that if you slice a string, you get a string back. If you slice a list, you get a list back, even if you only reference one item.

Slices also let you use negative indices, and you can omit one or two of the indices.

From the Python documentation:

word[-1]     # The last character
'A'
word[-2]     # The last-but-one character
'p'
word[-2:]    # The last two characters
'pA'
word[:-2]    # Everything except the last two characters
'Hel'

A really nice feature (from the Python documentation):

Degenerate slice indices are handled gracefully: an index that is too large is replaced by the string size, an upper bound smaller than the lower bound returns an empty string.

Slices are discussed in detail here. You should take some time to understand them, since they can be confusing at times.

Grouping statements

In C++, braces are used to group statements:

void foo()
{
    statement-1;
    statement-2;
}

In Python, indentation is used:

def foo():
    statement-1
    statement-2

Batteries included

Python is commonly referred to as having batteries included. The meaning of that phrase is that it comes with a large module library, which automates lots of common tasks. Here's an example:

When I wrote a command line daemon application in C#, I had to write my own class (128 lines of code) for parsing command line parameters. Not a big deal, but when I wrote a backup script in Python...

# This module comes with Python
from optparse import OptionParser

# ... in main

# Setup the parser
parser = OptionParser()

parser.add_option("--source", "-s",
                      help="The source directory.", dest="source")
parser.add_option("--dest", "-t",
                       help="The destination directory.", dest="dest")

# Parse the args
(options, args) = parser.parse_args(argv)

8 lines vs 128. Python was much faster than C# in terms of time spent on coding for the same task.

Returning multiple values

Every programmer has had to do it at one point or another, and in most languages, it's not pretty.

Here's a C++ example (using reference parameters):

void Foo(int &bar1, int &bar2, int &bar3)
{
	bar1 = 5;
	bar2 = 6;
	bar3 = 7;
}

// Method call example
int i, j, k;
Foo(i, j, k);

In Python:

def Foo():
    return 5, 6, 7

# Method call example
i, j, k = Foo()

5 lines vs 10. Python was faster.

Most Python developers will argue that you're not really returning multiple values, and they'd be right. However, it's seamless. It "just works".

In the interest of full disclosure, what really happened was:

def Foo():
    return tuple(5, 6, 7)

This page goes into a little more detail.

In the next tutorial, we'll talk about writing your first script.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>