Python For The Busy Java Developer: The Language, Syntax, and Ecosystem
Python For The Busy Java Developer: The Language, Syntax, and Ecosystem
Deepak Sarda
Python for the Busy Java Developer
Deepak Sarda
Singapore, Singapore
iii
Table of Contents
Classes�������������������������������������������������������������������������������������������������������������� 34
Inheritance�������������������������������������������������������������������������������������������������� 37
Polymorphism���������������������������������������������������������������������������������������������� 38
Getting Dynamic!����������������������������������������������������������������������������������������� 39
Protocols����������������������������������������������������������������������������������������������������������� 42
Organizing Code������������������������������������������������������������������������������������������������ 45
Importing code�������������������������������������������������������������������������������������������� 45
The main() Method�������������������������������������������������������������������������������������� 48
Summary���������������������������������������������������������������������������������������������������������� 57
iv
About the Author
Deepak Sarda has been working as a software
developer for more than twelve years, in
multiple business domains and in a variety of
technologies. He has worked on several high-
performance, server-side applications written
in Java, and has done web development and
systems automation work in Python.
He lives in Singapore with his lovely wife
and their adorable daughters. He can be found
online at antrix.net or @antrix on Twitter.
He’d love to hear what you’ve to say about this book. Please email him
at deepak@antrix.net.
v
About the Technical Reviewer
Chaim Krause is an expert computer
programmer with over 30 years of experience
to prove it. He has worked as a lead tech
support engineer for ISPs as early as 1995,
as a senior developer support engineer with
Borland for Delphi, and has worked in Silicon
Valley for over a decade in various roles,
including technical support engineer and
developer support engineer. He is currently
a military simulation specialist for the US
Army’s Command and General Staff College, working on projects such as
developing serious games for use in training exercises.
He has also authored several video training courses on Linux topics
and has been a technical reviewer on more than 20 books, including
iOS Code Testing by Abhishek Mishra (Apress, 2017), Android Apps for
Absolute Beginners by Wallace Jackson (Apress, 2017), and C# and XML
Primer: XML Essentials for C# and .NET Development by Jonathan Hartwell
(Apress, 2017). It seems only natural that he would be an avid gamer
and have his own electronics lab and server room in his basement. He
currently resides in Leavenworth, Kansas, with his loving partner, Ivana,
and a menagerie of four-legged companions: their two dogs, Dasher and
Minnie, and their three cats, Pudems, Talyn, and Alaska.
vii
Acknowledgments
I’d always heard it being said, but only now do I truly realize it: writing a
book is hard work! It would have been harder still had it not been for the
support from my family and friends.
I wish to especially thank Hitesh Sarda, Rohit Sharma, and Srijith Nair
for the incredibly detailed and thoughtful feedback that they provided as I
wrote this book. I owe many thanks to them.
I must also acknowledge the constant encouragement that I received
from my wife, Sonika. I can’t thank her enough for her patience and
support as I took time out to write this book.
ix
Introduction
Hello There!
If you are reading this book, then chances are that you are a busy Java
developer who is interested in learning Python. If so, I hope that by the
time you are done reading this short book.
This book is not for the beginner programmer. I assume that you
are comfortable programming in Java (or a similar language like C#),
and hence, I will not bore you with explanations of basic concepts like
variables, functions, and classes.
About the Book
This book is divided into three broad chapters:
• The Language
• The Syntax
• The Ecosystem
In the first chapter, we take a brief look at the Python language and
learn what it has to offer. Next, we’ll get down to the details of the syntax
before wrapping up with a look at the wider ecosystem surrounding the
Python language.
xi
CHAPTER 1
The Language
Let’s start our Python journey by first gaining an understanding of what
Python has to offer that’s different from Java. I’ll then help you get setup
with Python before we dive into the language’s syntax in the next chapter.
What Is Python?
Python is an “open source, general-purpose programming language that is
dynamic, strongly typed, object-oriented, functional, memory-managed,
and fun to use.” Those are a lot of adjectives for one sentence! Let’s unpack
them one at a time.
Python is distributed under an open source, BSD-style license called the
Python Software Foundation License Agreement. It is a very permissive
license that allows great flexibility in how Python can be used. Python’s
development is done in the open by a large and diverse community of
volunteers.
Python is general purpose in that you can use it to build a variety
of applications running the gamut from simple scripts and command-
line tools to desktop and web applications, network servers, scientific
applications, and more.
We know that Java is a statically typed language; that is, the types are
checked and enforced at compile time. In contrast, Python is dynamic,
which means that the types are checked only at runtime. But Python is
also strongly typed, just like Java. You can only execute operations that are
supported by the target type.
Another way to think about this is that in Java, both variables and
objects have types associated with them; whereas in Python, only objects
have types, not the variables that they are bound to. In Java, when we
declare
The obj variable is declared of type MyType and then the newly
instantiated object of type MyType is assigned to it. In contrast, in Python,
the same declaration would read
obj = MyType()
Ignoring the missing new keyword (which Python doesn’t have), obj is
simply a name that is bound to the object on the right, which happens to
be of type MyType. We can even reassign obj in the very next line—obj =
MyOtherType()—and it wouldn’t be a problem. In Java, this reassignment
would fail to compile1 while in Python, the program will run and will only
fail at runtime if we try to execute an operation via obj that is incompatible
with the type assigned to it at that point in time.
Python is object oriented and supports all the standard OOP features
that Java has like creation of types using classes, encapsulation of state,
inheritance, polymorphism, and so forth. It even goes beyond Java and
supports features such as multiple inheritance, operator overloading,
meta-programming, and so forth.
Python also supports a rich set of functional programming features
and idioms. In Python, functions are first-class objects that can be created,
manipulated, and passed around just like any other object. While its
emphasis on functional programming might not be as focused as say
1
Unless MyOtherType happens to be a subclass of MyType.
2
Chapter 1 The Language
H
istory
Python is the brainchild of a Dutch programmer named Guido van
Rossum. He started working on it when he got frustrated with the ABC
language in the late 1980s and after some years of private development,
he released the first version of Python in 1994. This actually makes
Python older than Java, the first version of which was released in 1996,
a full two years later! A comparison of the two languages is shown in
Table 1-1.
2
Even after the introduction of lambdas in Java 8.
3
Chapter 1 The Language
Java Python
Note I’ll use this tabular format to compare and contrast Python
and Java whenever it makes sense.
Since then, the language has continued to refine and evolve, with
Python 2.0 being released in 2000. As of this writing, the 2.x versions are
the most widely deployed.
In version 3.0, the language designers decided to break backward
compatibility in order to clean up some of the accumulated language
warts. Although this has been good from a language perspective, it has
been a significant hindrance to those upgrading from 2.x to 3.x. Imagine
if Sun had decided to introduce generics in Java 5 without type erasure,
thus breaking backward compatibility. The Java language would’ve been
much nicer today but the transition period would’ve been difficult, to say
the least. That is the kind of transition the Python user community is going
through right now.
4
Chapter 1 The Language
Note Since 2.x is still the most widely used version of Python,
this book will cover Python 2.x features and syntax, calling out any
differences with 3.x from time to time.
From the outset, Python’s development has been done in the open
with a community of volunteers contributing to the language and the core
libraries. Any language changes are proposed and discussed through a
process called PEP (Python Enhancement Proposals), with Guido having
final say in deciding the outcome. For his stewardship and continuous
involvement in the development of Python, Guido is affectionately called
the “Benevolent Dictator For Life.” He also periodically writes a Python
History blog3 chronicling the evolution of various language features.
I nstallation
This book is full of example code, and the best way to follow along is to
actually try these examples by yourself. To do this, you’ll obviously need to
install Python on your system. But an easier way is to check if you already
have access to a system with Python installed! Almost all systems running
Linux should have Python preinstalled. Recent versions of Mac OS X also
come with Python preinstalled. Just open a command shell on either of
these two systems and type in python. If you get a Python shell prompt,
you are all set! The version of Python installed may be a bit outdated but it
should be sufficient to get started.
3
http://python-history.blogspot.com/
5
Chapter 1 The Language
T ools
Python source code is organized in files with a .py extension. The python
executable interprets the source code and translates it into a Python
language–specific bytecode that is stored in .pyc files. This bytecode is
then executed by the Python virtual machine, which is also invoked by the
same python executable. Although this sounds like two steps, in reality, it
is just one step with the bytecode generation happening on the fly.
This is in contrast to Java (see Table 1-2), where the responsibilities for
the parsing and compilation of source code and the actual execution of
the compiled bytecode are split between javac and java respectively. In
Python, the python executable handles both steps. In fact, .pyc files are,
in effect, just intermediate caches to hold the translated bytecode. They
are not strictly necessary for execution. If you deleted the .pyc files, they’d
simply be regenerated the next time you ran the .py files.
.java .py
.class .pyc
Java.exe + javac.exe python.exe
IntelliJ IDEA PyCharm
Eclipse JDT PyDev
Java 9 JShell REPL
6
Chapter 1 The Language
There are multiple IDEs available for writing Python code. PyDev,
based on the Eclipse framework, and PyCharm, based on the IntelliJ IDEA
framework, are two of the more popular choices. While having an IDE is
nice, it is perfectly feasible to write Python code using a plain text editor
such as Vim4 or Sublime Text.
One interesting feature of Python that’s missing in Java is the REPL,
short for Read Eval Print Loop. A quick demo would be useful here. If
you’ve got access to a Python installation (follow the instructions in the
“Installation” section of this chapter), go ahead and launch a python shell,
as follows:
antrix@dungeon:~$ python
Python 2.7.5+ (default, Feb 27 2014, 19:39:55)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more
information.
>>>
>>> 10 + 10
20
>>>
4
Yes, Emacs is fine too.
7
Chapter 1 The Language
We typed in 10 + 10 at the prompt and hit the Enter key. The Python
REPL read this value, evaluated it, and printed the result. Then it went back
to the prompt to wait for our next input. Let’s try the following variable
assignment:
>>> x = 10
>>>
In this case, we didn’t see any output because what we entered was just
a statement, not an expression. But it did modify the state of the python
shell. If we query for x again, we’ll find this:
>>> x = 10
>>> x
10
>>>
>>> help(x)
>>>
8
Chapter 1 The Language
The full documentation view for an object can be quite verbose. If you
just want a quick overview of what attributes an object supports, use the
dir function.
>>> dir(x)
>>>
>>> x.numerator
10
>>> x.denominator
1
>>> x.conjugate
<built-in method conjugate of int object at 0x9e9a274>
9
Chapter 1 The Language
>>> x.conjugate()
10
You can also use the dir() function without any argument to get a list
of built-ins.
>>> dir()
>>> dir(__builtins__)
10
Chapter 1 The Language
>>>
This gives a list of functions and other objects that are built-in and do
not have to be imported from other packages. This is analogous to how
everything defined in the java.lang package is available everywhere in
Java without having to explicitly import it.
Tip The dir and help functions are extremely useful when doing
exploratory development in a Python interactive shell.
There’s one last thing I wish to show before we wrap up this section.
Let’s create a new file named hello.py with the following contents:
11
Chapter 1 The Language
Summary
In this chapter, we learned that Python is not just a scripting language but a
general-purpose programming language with a long history behind it. We
then got familiar with the python executable, the Python counterpart of the
java and javac executables.
We also looked at the Python REPL environment, which is a great way
to interactively try out Python. If you still don’t have the REPL set up, I urge
you to do so now because the next chapter makes extensive use of it as we
dive into the nitty-gritty details of the language’s syntax!
12
CHAPTER 2
The Syntax
This chapter is the heart of the book. It is a deep dive into Python language
features. I explain them using short code fragments that you can easily try
out yourself.
We start by introducing the basic data types and built-in collections
such as dictionaries and sets, with a special emphasis on lists. We’ll then
dive into functions and discover their power as a first-class language
feature.
Moving on to classes, we’ll find out how flexible Python is as an
object-oriented language, especially compared to Java. We’ll then explore
protocols, which extend the language’s syntax to your own types.
Finally, we’ll discuss the concepts of modules and packages as a means
of organizing Python code.
As you can see, it is going to be a long chapter. So grab some coffee and
let’s get started!
H
ello World
>>> print "Hello World"
Hello World
>>>
Tip In Python 3, the print keyword has been replaced with the
print() function.
Basic Constructs
Here’s a bit of Python code that, well, I don’t have to tell you what it
does, do I? Most Python code is like this: eminently readable and almost
pseudo-code-like.
You must have noticed a few things, such as the lack of semicolons as
statement separators. Let’s work through this code one line at a time to see
what else is new and different compared to Java.
14
Chapter 2 The Syntax
15
Chapter 2 The Syntax
Basic Types
Some of the basic data types in Python are numbers, strings, and
collections.
Numbers
Numbers come in the following variety.
int 1000
long 1000L
float 1000.12
complex 1000 + 12j
Although int and long are different data types, in practice, you only
need to worry about them when declaring literal values; that is, literal
longs need to be declared with a L suffix. During arithmetic operations,
Python automatically converts int values to long values as needed. This
also prevents overflow-related bugs.
16
Chapter 2 The Syntax
Strings
As in Java, strings are immutable in Python. String values can be wrapped
in either single or double quotes. To differentiate between vanilla ASCII
strings and Unicode strings, Python uses the u prefix to denote the latter.
Unicode strings provide additional operations related to encoding/
decoding from various character sets.
str 'apple'
unicode u'äþþĺė'
str r'C:\temp'
A third type of string is the raw string denoted by the r prefix. This is
just an indication to the Python parser to not apply any backslash escaping
rules to the string. Here’s a quick example that illustrates the difference.
17
Chapter 2 The Syntax
As you can imagine, raw strings are extremely useful when denoting
file system paths or regular expressions.
Collections
The built-in Python collections come in four varieties.
Tip While tuple and list may look similar, the distinction is that
a tuple is immutable.
18
Chapter 2 The Syntax
Fun with Lists
Lists are the workhorse data structure in Python and I exaggerate only
slightly when I say that mastering them is the key to mastering Python!
Although earlier I said that they are like java.util.ArrayList, they
are truly much more than that. But first, let’s look at a short example
demonstrating their use as a basic array.
Apart from single element access, what sets apart Python lists is the
ability to extract element ranges from lists. This is accomplished using the
slice syntax. Here’s how.
>>> numbers[0:4] ①
[0, 1, 2, 'three']
>>> numbers[:4] ②
[0, 1, 2, 'three']
19
Chapter 2 The Syntax
>>> numbers[4:] ③
[4, 5, 6, 7, 8, 9]
>>> numbers[2:-2] ④
[2, 'three', 4, 5, 6, 7]
>>> numbers[0:9:2] ⑤
[0, 2, 4, 6, 8]
>>> numbers[::2] ⑥
[0, 2, 4, 6, 8]
>>> numbers[::-1] ⑦
[9, 8, 7, 6, 5, 4, 'three', 2, 1, 0]
20
Chapter 2 The Syntax
3. But the two lists are not the same object. This is
similar to comparison using == in Java.
Now let’s turn our eyes toward performing operations on lists. The
first thing one would want to do with a list is to iterate over its elements.
There are a few different variants of list iteration in Python, either using the
vanilla foreach style syntax or augmenting it with the enumerate, range,
and len built-in functions.
21
Chapter 2 The Syntax
>>> toys.append('doll')
>>> print toys
['bat', 'ball', 'truck', 'doll']
>>> toys.remove('ball')
>>> print toys
['bat', 'truck', 'doll']
>>> toys.sort()
>>> print toys
['bat', 'doll', 'truck']
22
Chapter 2 The Syntax
>>> stack = []
>>> stack.append("event") # Push
>>> event = stack.pop() # Pop
>>>
>>> queue = []
>>> queue.append("event") # Push
>>> event = queue.pop(0) # Pop from beginning
There are many more operations that a list provides, such as extend,
insert, and reverse. But let’s now look at one of the most interesting
features of lists: comprehensions.
Consider the following code, which computes the factorial of the first
few integers:
>>> factorials = []
23
Chapter 2 The Syntax
If the list/object being iterated over is large (or even unbounded), then
a variant of the list comprehension syntax called generator expressions can
be used. In the following snippet, factorials_of_odds is lazily computed
as you iterate over it.
24
Chapter 2 The Syntax
ASIDE
With that rather verbose introduction to lists, let’s turn our attention
toward one of the core building blocks of procedural programming:
functions.
Functions
Functions in Python are quite a bit more flexible than in Java.
25
Chapter 2 The Syntax
Function definitions begin with the def keyword (Hello, Scala and
Groovy!) followed by the parameter list in parentheses. Once again, there
are no curly braces, and only the indentation defines the scope of the
function body.
Note For now, please ignore the strange looking asterisk prefix in
front of args and kwargs in this function’s parameter declaration. It
is a special bit of syntax that I’ll describe in the next section.
>>> help(a_function)
Help on function a_function in module __main__:
26
Chapter 2 The Syntax
ASIDE
Let’s see how a_function (as defined earlier) behaves when called
with different argument values.
>>> a_function(10) ①
arg1: 10
arg2: default
args: ()
kwargs: {}
27
Chapter 2 The Syntax
28
Chapter 2 The Syntax
Functions and Tuples
Python functions hold one more trick up their sleeve: support for multiple
return values!
def multi_return():
# These are automatically wrapped up
# and returned in one tuple
return 10, 20, 'thirty'
29
Chapter 2 The Syntax
>>> a, b, c = multi_return() ③
>>> print a, b, c
10 20 thirty
What happened here is that first, Python packed the multiple return
values from multi_return into a single tuple. Then, it transparently
unpacked the returned tuple and assigned the contained values to the
corresponding variables on the left of the assignment.
For this to work, the number of variables on the left must match the
number of elements being returned by the called function; otherwise, an
error is raised.
>>> a, b = multi_return()
ValueError: too many values to unpack
Now that you know how tuple packing and unpacking works, let’s
revisit the strange looking asterisks in *args and **kwargs that we
encountered in the previous section. The leading single asterisk is Python
notation to unpack the tuple values while the leading double asterisk
unpacks the dict values. Here’s an example that demonstrates this:
>>> ternary(1, 2, 3)
1 2 3
30
Chapter 2 The Syntax
def make_function(parity): ①
"""Returns a function that filters out `odd` or `even`
numbers depending on the provided `parity`.
"""
if parity == 'even':
matches_parity = lambda x: x % 2 == 0 ②
elif parity == 'odd':
matches_parity = lambda x: x % 2 != 0
else:
raise AttributeError("Unknown Parity: " + parity) ③
def get_by_parity(numbers): ④
filtered = [num for num in numbers if matches_parity(num)]
return filtered
return get_by_parity ⑤
#
31
Chapter 2 The Syntax
32
Chapter 2 The Syntax
1
See steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
33
Chapter 2 The Syntax
C
lasses
Everything in Python is an object and as you’d expect, the way to create
objects is to start from classes. Consider the following definition of a
simple Person class.
class Person(object):
def __init__(self, first, last):
self.first = first
self.last = last
def full_name(self):
return "%s %s" % (self.first, self.last)
def __str__(self):
return "Person: " + self.full_name()
As in Java, object is at the root of the class hierarchy but unlike Java,
it needs to be specified explicitly in Python (although not in Python 3).2
Inheritance declarations do not use a special keyword like extends. Instead,
the parent class' name is enclosed within parentheses after the declaring
class’s name.
The __init__ method is the initializer method and is analogous
to the Java class constructor. There is also a constructor method called
__new__ but you won’t use it unless you are doing metaprogramming like
writing factory classes, and so forth. Within __init__, all the instance
fields — called attributes in Python — are initialized. Note that we did not
have to pre-declare all the attributes of the class.
You may skip specifying object as the base class in Python 2, but it’ll have implications
2
34
Chapter 2 The Syntax
ASIDE
35
Chapter 2 The Syntax
36
Chapter 2 The Syntax
Inheritance
Python supports single inheritance as well as multiple inheritance; that is,
the inheritance model is closer to C++ than Java. With multiple inheritance,
there’s always the question of how methods are resolved when declared
at multiple places in the class hierarchy. In Python, the method resolution
order is in general, depth-first. The class attribute __mro__ can be inspected
to check the actual method resolution order being used for the class.
Here’s a SuperHero class that extends the Person class that we
previously defined. We’ve added one new attribute, nick, and one new
method, nick_name, in the SuperHero class.
class SuperHero(Person):
def __init__(self, first, last, nick):
super(SuperHero, self).__init__(first, last)
self.nick = nick
def nick_name(self):
return "I am %s" % self.nick
super works like it does in Java, but once again, you need to be
explicit about the class at which it should start climbing up. Let’s see how
SuperHero behaves in a few examples.
>>> p.nick_name()
I am Superman
>>> p.full_name()
'Clark Kent'
>>> type(p) ①
<class '__main__.SuperHero'>
>>> type(type(p))
<type 'type'>
Polymorphism
Let’s look at the canonical example that is used to demonstrate
polymorphic behavior, the shape.
class Square(object):
def draw(self, canvas):
...
38
Chapter 2 The Syntax
class Circle(object):
def draw(self, canvas):
...
Given these two Square and Circle classes, the Java developer inside
you would already be thinking of extracting a Shape class or interface
that defines the draw(canvas) method. Resist that urge! Since Python is
dynamic, the following code works just fine without an explicit Shape class:
Getting Dynamic!
So far, what we’ve seen of classes in Python is pretty tame. There’s nothing
that you couldn’t accomplish in Java. Time to make it interesting! Consider
the following:
39
Chapter 2 The Syntax
40
Chapter 2 The Syntax
>>>
class Person(object):
...
41
Chapter 2 The Syntax
P
rotocols
Protocols are like Java interfaces in that they define one or more methods
that offer a particular behavior. However, unlike Java interfaces, protocols
are not explicitly defined in source code. The closest equivalent would
be the equals(), hashcode(), and toString() methods in Java. These
methods aren’t part of any explicit interface. Yet, we have an implicit
convention3 that these methods will be invoked in certain situations. So it
is with Python protocols.
The Python language defines several different protocols such as
sequences, numeric, containers, and so forth. These protocols manifest
themselves in terms of special syntactic support in the language grammar.
Pretty much every language syntax in Python is implemented in terms
of protocols, and thus, can be made to work with your own types by
implementing the relevant protocols.
Let me explain this further using one of the protocols, the Container
protocol, as an example. Consider the following OrderRepository class
definition, which provides access to a database backed collection of Order
objects.
3
convention documented in the Java Language Specification, but a convention
A
nevertheless; not a source code level contract.
42
Chapter 2 The Syntax
class OrderRepository(object):
...
def __contains__(self, key):
return 1 == db.query("select count(1) from Orders where
id='%s'" % key)
I’ve elided the full class definition and only shown the three methods that
are part of the Container protocol. Since OrderRepository can now be said to
implement the Container protocol, it allows us to use it in the following way:
43
Chapter 2 The Syntax
44
Chapter 2 The Syntax
Organizing Code
The most basic unit of source code organization in Python is the module,
which is just a .py file with Python code in it. This code could be functions,
classes, statements or any combination thereof. Several modules can
be collected together into a package. Python packages are just like Java
packages, with one difference: the directory corresponding to a package
must contain an initializer file named __init__.py. This file can be empty
or it can optionally contain some bootstrap code that is executed when the
package is first imported.
Suppose we have a code base organized, as follows:
.
|-- cart.py
|-- db
| |-- __init__.py
| |-- mysql.py
| +-- postgresql.py
+-- model
|-- __init__.py
+-- order.py
Given this directory listing, we can see that there are two packages: db
and model. There are four modules: cart, mysql, postgresql, and order.
Importing code
Importing code defined in one file (or module, in Python terms) into
another is accomplished using the import statement. The import
statement works pretty much like it does in Java: it brings the declarations
from the target module into the current namespace.
45
Chapter 2 The Syntax
There are two syntactical variants of the import statement. The first
one is in the familiar Java style, import ... while the second one follows a
from ... import ... pattern.
Suppose we have a class named SellOrder defined in the order
module; that is, inside the order.py file:
$ cat model/order.py
class SellOrder(object):
...
...
There are a few different ways in which we can import and use this
class in our main app, cart.py.
import model
sell_order = model.order.SellOrder()
import model.order
sell_order = order.SellOrder()
sell_order = SellOrder()
46
Chapter 2 The Syntax
print ORDER_TYPES
# ['buy', 'sell']
print DATABASE_TYPES
# ['mysql', 'postgresql']
As you can imagine, this feature comes in very handy when trying to
avoid namespace conflicts without having to use the full package/module
hierarchy for disambiguation like we do in Java.
Tip In Java, each .java file must contain only class or interface
declarations at the top level. Moreover, in typical usage, each such
file has just one public class or interface defined. Python modules
have no such restrictions. It is perfectly fine to create modules with
just functions or just classes or a mix of both. Do not restrict yourself
to just one class or function definition per module. This is not only
unnecessary, but also considered a bad practice. Instead, strive to
collect constructs having conceptual similarity into one module.
47
Chapter 2 The Syntax
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
odds_until = 10
numbers = range(odds_until)
print get_odds(numbers)
48
Chapter 2 The Syntax
$ python odds.py
[1, 3, 5, 7, 9]
$
Having seen how Python executes a script, we can try and simulate a
main method, as follows:
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
def main():
odds_until = 10
numbers = range(odds_until)
print get_odds(numbers)
main()
49
Chapter 2 The Syntax
All we’ve done here is wrapped up all our top-level statements into a
function that we conveniently gave the name of main! We call this function
at the end of the file, in effect, making main the entry point of our app.
Let’s complete our Java-like main method implementation by taking
care of the arguments to main; that is, the args in public static void
main(String[] args). In Java, all command-line parameters passed to
the application during launch would be populated in the args arrays. In
Python, this information is available using the built-in sys standard library
module. This module defines sys.argv, which is a list of the command-
line arguments passed to the Python script on startup. The first value in
the list, sys.argv[0] is the name of the script itself. The remaining items in
this list are the command-line arguments, if any.
Let’s modify our odds.py script to take the number, until which we
should print odd numbers as a command-line parameter, which we
retrieve using the sys module.
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
def main(args):
try:
odds_until = int(args[1])
except:
print "Usage: %s <number>" % sys.argv[0]
sys.exit(1)
numbers = range(odds_until)
print get_odds(numbers)
import sys
main(sys.argv)
50
Chapter 2 The Syntax
In this modified odds.py, we invoke the main function with the list of
command-line arguments as a parameter. Within main, we initialize the
odds_until variable using the first command-line argument. If this fails for
any reason, we print a helpful message on how to use the script before exiting
with a 1 error code. Here’s how this modified example works in practice:
$ python odds.py
Usage: odds.py <number>
$ python odds.py abc
Usage: odds.py <number>
$ python odds.py 15
[1, 3, 5, 7, 9, 11, 13]
$
Finally, we have a main function that works like Java! It even looks
like the main method in Java; def main(args) is more or less identical
to public static void main(String[] args) once all the type-related
declarations are dropped.
However, there’s a wrinkle here that I wish to talk about. Imagine that
we found our get_odds function to be so useful that we wanted to use it as
a utility function elsewhere in our project’s codebase. Since we just talked
about modules, the obvious way would be to just use odds.py as a module
and import the module wherever we find the use of this utility function.
For example, in demo.py:
# demo.py
import odds
print odds.get_odds(range(10))
51
Chapter 2 The Syntax
$ python demo.py
Usage: demo.py <number>
$
import sys
main(sys.argv)
52
Chapter 2 The Syntax
Caution Unless you have a very good reason, do not define any
side effect–causing top-level statements in your modules. If you
do so, these statements will be executed whenever your module is
imported causing all sorts of headaches.
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
$ python demo.py
[1, 3, 5, 7, 9]
Having made this change, while we gained the ability to use odds as
a module, we lost the ability to run it as a script. Wouldn’t it be nice if
we could do both? Even in Java land, just because a class defines a main
method does not mean that it can’t be imported and used as a vanilla class
elsewhere!
To achieve this module/script duality, we’ll have to dig a little bit
deeper into the notion of namespaces.
I’ve mentioned the term namespace several times in this chapter
without defining it in more detail. In computer science terms, we
understand namespaces as isolated contexts or containers for names.
Namespaces allow us to group logical things together and allow reuse of
names without causing conflicts.
53
Chapter 2 The Syntax
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
# demo.py
import odds
print odds.get_odds(range(10))
$ python demo.py
In odds, __name__ is odds
In demo, __name__ is __main__
[1, 3, 5, 7, 9]
54
Chapter 2 The Syntax
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
def main(args):
try:
odds_until = int(args[1])
except:
print "Usage: %s <number>" % sys.argv[0]
sys.exit(1)
numbers = range(odds_until)
print get_odds(numbers)
import sys
main(sys.argv)
55
Chapter 2 The Syntax
We will wrap up the top-level code behind a check for the current
namespace:
# odds.py
def get_odds(numbers):
odds = [n for n in numbers if n % 2 != 0]
return odds
def main(args):
try:
odds_until = int(args[1])
except:
print "Usage: %s <number>" % sys.argv[0]
sys.exit(1)
numbers = range(odds_until)
print get_odds(numbers)
if __name__ == '__main__':
import sys
main(sys.argv)
As you can see, we took the side-effect causing top-level code, namely
the invocation of the main() function, and put it behind a conditional that
checks if the current namespace is __main__. When odds.py is run as a
script; that is, it is the entry point of the application, the value of __name__
will be __main__. Thus, we will enter the conditional block and run that
piece of code. On the other hand, when odds.py is imported as a module,
the value of __name__ will be odds and not __main__. Thus, the block of
code behind the conditional is skipped.
56
Chapter 2 The Syntax
As you read more and more Python code, you’ll come across the
if __name__ == '__main__' construct all the time. It is a standard idiom
used in Python programs to get the effect of a main method. Python’s
creator, Guido van Rossum, has written a nice blog post on writing
idiomatic Python main() functions4 that takes this idea even further.
S
ummary
We covered quite a bit of ground in this chapter. We started with a look at
the basic syntax and built-in types that Python provides. We then moved
on to the building blocks of functions and classes. We then familiarized
ourselves with Python’s implicit interfaces; that is, protocols. Finally, we
learned about organizing source code into modules and packages.
While this book ends our discussion of Python language syntax over
here, there’s more to Python than this! Some of the advanced topics
that we didn’t discuss include decorators, properties, generators, context
managers, and I/O. These are topics you’ll find yourself exploring once
you get comfortable writing basic Python code. To help you along in your
learning, I’ve compiled some useful resources in “References” section at
the end of this book.
4
See http://www.artima.com/weblogs/viewpost.jsp?thread=4829
57
CHAPTER 3
The Ecosystem
As software developers, we know that when evaluating a programming
language, we need to look at not just the core language itself, but also
at the ecosystem of libraries and tools for the language. The richness of
this ecosystem often determines how productive you’d be when writing
software in the language.
In this chapter, I describe the Python ecosystem and share some of
the more popular tools and frameworks to get you started with Python
development.
A Rich Ecosystem
In the Java world, we know that Java is much more than the language
itself. There’s the JVM, the Java language runtime that allows deploying
applications on a variety of hardware and operating system targets. There
are the Java SE and EE Standard Libraries, which provide a lot of useful
functionality out of the box. And of course, there’s an immensely rich
variety of third-party libraries and frameworks to choose from. It is the
strength of this ecosystem that makes Java a great platform to build upon.
So it is with Python!
Python too can be deployed on different hardware targets like x86,
ARM, and MIPS; on multiple operating systems like Linux, Mac OS X,
P
opular Tools
In the Python world, third-party library installation is typically done
using a tool named pip. It can read the requisite third-party package
dependencies for your project from a standardized requirements.txt file,
and then install/upgrade packages as necessary. If needed, it can even
download packages from a central repository named PyPI, short for the
Python Package Index. This is the Python world’s equivalent of Maven’s
Central Repository.
1
http://ironpython.net/
2
http://www.jython.org/
60
Chapter 3 The Ecosystem
Java Python
build.xml/pom.xml requirements.txt
Maven pip
Maven Central repository PyPI
Classpath PYTHONPATH
HotSpot CPython
With third-party packages comes the question of how they are located
at runtime. Java’s solution is the classpath and Python’s equivalent is the
PYTHONPATH. Conceptually, they are similar in that both specify a list of
locations where the language runtime should search for packages being
imported. Implementation wise, they differ a bit. PYTHONPATH is set as an
environment variable; for example, PYTHONPATH=/path/to/foo:/path/
to/bar, a syntax similar to the typical system shell’s PATH variable. Another
flexibility that Python provides is that this library search path can be
modified at runtime just by manipulating the sys.path attribute exposed
by the built-in system module. As you might have guessed, sys.path is
initialized from the value set for the PYTHONPATH environment variable.
I mentioned earlier that there are multiple runtime implementations
of the Python language. The canonical implementation is CPython, named
so because the core of the language runtime is implemented in C. It is
the most widely used implementation and regarded as the reference for
the Python language. Alternative implementations include Jython, which
61
Chapter 3 The Ecosystem
Popular Frameworks
Since Python is a dynamic language, there’s a class of programming errors
that are revealed at runtime, instead of being caught at compile time like
they would in a statically typed language. Thus, writing automated tests
for your Python programs is even more important than it is in Java. The
Python standard library ships with a unit-testing framework creatively
named unittest, which should serve as good start. If you find that unittest
is missing some features you’d like or is just a bit too cumbersome to use,
then pytest is a good third-party alternative.
62
Chapter 3 The Ecosystem
JUnit unittest/pytest
Mockito unittest.mock
Findbugs/Checkstyle pylint
Javadoc Sphinx
Swing PyQT/PyGTK
Spring Boot Django/Flask
Hibernate SQLAlchemy
Velocity/Thymeleaf Jinja2
Servlets WSGI
Tomcat/Jetty Apache/uWSGI
63
Chapter 3 The Ecosystem
surprised to know that many of the Internet’s most popular websites, like
YouTube and Reddit, are written in Python.
Spring Boot is a popular choice for full stack web development in the
Java world. By full stack, I mean a framework that handles everything
from frontend user authentication to backend database connectivity and
everything in between. The most popular full-stack web development
framework for Python is Django. If you are just dipping your toes into
web development with Python, I strongly recommend that you start
with Django. You’ll find it to be a very easy to learn and productive web
development environment.
On the other hand, if you are the type of developer who finds full
stack frameworks too restrictive to use, then you can mix and match best
of breed libraries and roll your own stack. On the database access front,
SQLAlchemy is the preeminent option. It provides a low-level DB interface
like JDBC, a mid-level Spring JDBCTemplate like interface that provides
convenient plumbing around writing raw SQL queries, and finally, a high-
level ORM layer like Hibernate. Depending on your requirements, you can
choose just the level of abstraction that you need.
Another aspect of web development is generating responses for HTTP
requests, typically HTML pages, using a template engine. This is the kind
of work for which you’d reach for the Velocity or Thymeleaf libraries over
in Java land. Jinja2 is the go-to templating library for Python applications.
It has a pleasant syntax, lots of features, and is fairly fast too.
Python web sites are generally deployed using either the Apache web
server or a smaller Python specific web server like uWSGI. These web
servers rely on a Python web development standard called the Web Server
Gateway Interface (WSGI). Think of it as the equivalent of Java servlets in
the Python world.
64
Chapter 3 The Ecosystem
Summary
Due to its long history and popularity, Python has gained a rich ecosystem
of libraries, tools, and frameworks that aid software development. We
discussed a few of the popular ones in this chapter that should help you get
started on your first Python project.
65
CHAPTER 4
antrix@cellar:~$ python
>>> import this
1
See http://www.wefearchange.org/2010/06/import-this-and-zen-of-
python.html
68
APPENDIX
References
• Code Like a Pythonista: Idiomatic Python
http://python.net/~goodger/projects/
pycon/2007/idiomatic/handout.html
http://www.dabeaz.com/generators-uk/
http://dirtsimple.org/2004/12/java-is-not-
python-either.html
http://mirnazim.org/writings/python-
ecosystem-introduction/
http://dirtsimple.org/2004/12/python-is-not-
java.html
http://farmdev.com/src/secrets/
http://legacy.python.org/dev/peps/pep-0008/
http://docs.python-guide.org/en/latest/
70
Index
A, B, C, D J, K, L
Command-line arguments, 51 Java virtual machine (Jython), 60
Jython, 61
E, F, G, H
Ecosystem M, N, O
build and execution tools, 61 Method resolution order, 37
Django, 64
frameworks, 62, 64
frameworks landscape, 60 P, Q
hardware targets, 59 Polymorphism, 38–39
Java SE and EE Standard Python
Libraries, 59 functional programming, 2
Jython, 61 history, 3, 5
PyQT and PyGTK libraries, 63 installation, 5
PYTHONPATH, 61 JVM garbage collectors, 3
SQLAlchemy, 64 memory management, 3
third-party libraries, 60 object oriented programming, 2
third-party libraries and obj variable, 2
frameworks, 59 Python Software Foundation
License Agreement, 1
scripts and command-line
I tools, 1
Inheritance, 37–38 tools
IronPython, 60 built-in functions, 8
72