Python is Awesome

@JaceBrowning

From Wikipedia:

Python is a widely used general-purpose, high-level programming language.

Its design philosophy emphasizes code readability, and its syntax allows programmers to express concepts in fewer lines of code

Everything is an Object

In Python, everything is an object. Objects are first-class and can be stored in variable and passed to functions.

In [16]:
x = [1, 2, 3, 'a', 'b', 'c']

x
Out[16]:
[1, 2, 3, 'a', 'b', 'c']
In [17]:
y = x

y
Out[17]:
[1, 2, 3, 'a', 'b', 'c']
In [18]:
x.append("this")

x
Out[18]:
[1, 2, 3, 'a', 'b', 'c', 'this']
In [19]:
x.append
Out[19]:
<function append>
In [20]:
a_func = x.append

a_func
Out[20]:
<function append>
In [21]:
a_func("that")

x
Out[21]:
[1, 2, 3, 'a', 'b', 'c', 'this', 'that']
In [26]:
type(x)
Out[26]:
list
In [27]:
a_class = type(x)

a_class
Out[27]:
list
In [28]:
z = a_class()

type(z)
Out[28]:
list

Useful Built-in Types

Python's built-in types are good enough in many situations and work together in predictable ways.

In [29]:
my_int = 42
my_float = 42.0
my_str = "42"
my_bool = True
In [30]:
my_int == my_float
Out[30]:
True
In [33]:
str(my_int) == my_str
Out[33]:
True
In [34]:
bool(my_int) == my_bool
Out[34]:
True
In [35]:
[my_int, my_float, my_str, my_bool]
Out[35]:
[42, 42.0, '42', True]
In [36]:
{'numbers': (my_int, my_float), 'others': (my_str, my_bool)}
Out[36]:
{'numbers': (42, 42.0), 'others': ('42', True)}

Dynamic (Duck) Typing

Python data types are checked at run-time and not bound to a variable. Functions do not necessarily care about the types of objects passed to them.

In [37]:
my_list = [1, 4.2, True, "Hello, world!"]
In [38]:
len(my_list)
Out[38]:
4
In [39]:
my_str = my_list[-1]

my_str
Out[39]:
'Hello, world!'
In [40]:
len(my_str)
Out[40]:
13
In [41]:
a = my_str.split(',')[0] + '!'

a
Out[41]:
'Hello!'
In [42]:
a = my_list[1:3]

a
Out[42]:
[4.2, True]

Chained Comparison Opperators

Pretty basic math, but many languages lack this.

In [43]:
x = 42
In [44]:
40 < x < 99
Out[44]:
True
In [45]:
1 <= x < 40
Out[45]:
False

Numerical Literals

Integers can take whatever form you need them in.

In [46]:
65 == 0x41 == 0b01000001 == ord('A')
Out[46]:
True

List Comprehension

The built-in container types can be dynamically constructed.

In [47]:
[x for x in range(10)]
Out[47]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [48]:
[x * 1.5 for x in range(10)]
Out[48]:
[0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0, 13.5]
In [49]:
[x * 1.5 for x in range(10) if x > 4]
Out[49]:
[7.5, 9.0, 10.5, 12.0, 13.5]
In [50]:
{x: x * 1.5 for x in range(10)}
Out[50]:
{0: 0.0,
 1: 1.5,
 2: 3.0,
 3: 4.5,
 4: 6.0,
 5: 7.5,
 6: 9.0,
 7: 10.5,
 8: 12.0,
 9: 13.5}

String Formatting

Python contains a mini-language for string formatting (in addition to C-style string formatting).

In [51]:
"vehicle '{0}' has wheel count: {1}".format('car', 4)
Out[51]:
"vehicle 'car' has wheel count: 4"
In [52]:
"a score of {:.2%}".format(.96578)
Out[52]:
'a score of 96.58%'
In [53]:
"{:,}".format(1000000)
Out[53]:
'1,000,000'
In [54]:
"{:.2e}".format(1000000)
Out[54]:
'1.00e+06'

Keyword Arguments

Functions arguments can be applied by position or name.

In [55]:
def total(sub, tip, tax=0.06):
    return sub + (sub * tax) + tip
In [56]:
total(10.0, 2.0)
Out[56]:
12.6
In [57]:
total(10.0, 2.0, 0.10)
Out[57]:
13.0
In [58]:
total(10.0, 2.0, tax=0.05)
Out[58]:
12.5
In [59]:
total(10.0, tax=0.09, tip=1.5)
Out[59]:
12.4

Data Model

Python's "magic" methods make defining custom classes work well with duck typing.

In [69]:
class Person(object):
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __str__(self):
        return "{n} is {a}".format(n=self.name, a=self.age)
    
    def __iadd__(self, years):
        self.age += years
        return self
    
    def __cmp__(self, other):
        return cmp(self.age, other.age)
    
In [70]:
person = Person("John Smith", 42)
In [71]:
print person
John Smith is 42

In [72]:
person += 1
In [73]:
print person
John Smith is 43

In [74]:
person > Person("Jane Doe", 42)
Out[74]:
True

Explicit Namespaces

In Python, namespaces are explicit. To refernce an object, it must be in your local or global namespace (or built-in).

In [76]:
class Foo(object):
    
    BAR = 1
    
    def __init__(self, value):
        self.value = value  # creation of self.value
        
    def __str__(self):
        text = ""
        text += str(self.value)  # instance variable
        text += ', '
        text += str(self.BAR)  # class variable
        return text
        
print Foo(2)
2, 1

Decorators

The decorator syntax allow dynamic modification of attributes.

In [77]:
def show_call(func):
    print "called {0}".format(func.__name__)
    return func
In [78]:
class Foo(object):
    
    BAR = 1
    
    @show_call
    def __init__(self, value):
        self.value = value  # creation of self.value
        
    @show_call
    def __str__(self):
        text = ""
        text += str(self.value)  # instance variable
        text += ', '
        text += str(self.BAR)  # class variable
        return text
        
print Foo(2)
called __init__
called __str__
2, 1

Standard Libraries

Python's standard library contains many useful modules.

In [79]:
from collections import Counter

for char, count in Counter("The quick brown fox jumped over the lazy dog.").items():
    if count > 1 and char != ' ':
        print char, count
e 4
d 2
h 2
o 4
r 2
u 2

In [80]:
from itertools import permutations

for permutation in permutations(('a', 'b', 'c')):
    print permutation
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')

And many more:

External Libraries

The above concepts and many more allow the creation of useful and friendly 3rd-party libraries.

Primary Hosting

http://pypi.python.org

Most packages can be installed with pip:

pip install ProjectName
In [81]:
>>> import requests

>>> requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200

>>> r.headers['content-type']
'application/json; charset=utf8'

>>> r.encoding
'utf-8'

>>> r.text
u'{"type":"User"...'

>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77}
  File "<ipython-input-81-04b2ed99ac4a>", line 17
    {u'private_gists': 419, u'total_private_repos': 77, ...}
                                                        ^
SyntaxError: invalid syntax
In []:
>>> from suds.client import Client

>>> url = 'http://localhost:7080/webservices/WebServiceTestBean?wsdl'
>>> client = Client(url)

>>> print client

Service (WebServiceTestBeanService) tns="http://test.server.enterprise.rhq.org/"
   Prefixes (1):
     ns0 = "http://test.server.enterprise.rhq.org/"
   Ports (1):
     (Soap)
       Methods:
         addPerson(Person person, )
         echo(xs:string arg0, )
         getList(xs:string str, xs:int length, )
         getPercentBodyFat(xs:string name, xs:int height, xs:int weight)
         getPersonByName(Name name, )
         hello()
         testExceptions()
         testListArg(xs:string[] list, )
         testVoid()
         updatePerson(AnotherPerson person, name name, )
   Types (23):
     Person
     Name
     Phone
     AnotherPerson
In []:
>>> from sh import git, ls, wc

>>> git(checkout="master")

>>> print ls("-l")

>>> longest_line = wc(__file__, "-L")
In []:
>>> import serial

>>> ser = serial.Serial('COM1')
>>> ser.write("hello")
>>> ser.close()
In []:
>>> from veracity import Repository, WorkingCopy, Item

>>> repo = Repository('veracity', remote='http://public.veracity-scm.com/repos/veracity')
>>> print repo.name
>>> print repo.users
>>> print repo.branches
>>> print repo.tags

>>> work = repo.checkout("~/v/veracity")
>>> work.delete()

>>> work = WorkingCopy("~/v/veracity", repo='veracity')
>>> work.update(branch='master')

>>> item = Item('docs/GettingStarted.txt', work=work)
>>> item.lock()

The End