Michael-Keith Bernard
mkbernard.dev@gmail.com
Twitter/Github/IRC: @SegFaultAX
Read-Eval-Print-Loop is a tool common to many languages. It enables rapid prototyping and exploratory programming. This talk is entirely in REPL format!
Just type "python" at the command line to start
Syntax and Structure
Standard Library
Open Source Ecosystem
Don't try and remember everything I talk about. Just listen and let it get into your consciousness.
This is not a CS101 talk
The only way to reach mastery is by years of dedicated effort and practice.
Don't sweat the small stuff! Don't worry about technical terms and complex-sounding words.
Full Name,Email,User Id
Brooke Bednar,Brenda@antoinette.com,0
Mrs. May Keeling,Penelope_McLaughlin@kari.org,1
"Dashawn Cummings, The Third",Dorothy@macey.biz,2
State the following as unambiguously as possible:
>>> 1
1
>>> 1.1
1.1
>>> 123 + 456
579
>>> 2 + 4 * 8
34
>>> 2 ** 32
4294967296
>>> 2 ** 128
340282366920938463463374607431768211456L
>>> 22 / 7
3
>>> 22 / 7.0
3.142857142857143
>>> True
True
>>> False
False
>>> True and False
False
>>> True and True
True
>>> False or True
True
>>> False or False
False
>>> not True
False
>>> not False
True
>>> def test():
... print "Got to test!"
... return True
...
>>> True or test()
True
>>> False or test()
Got to test!
True
>>> False or test() or test()
Got to test!
True
>>> True and test() and test()
Got to test!
Got to test!
True
>>> bool("Hello")
True
>>> bool(123)
True
>>> bool(0)
False
>>> bool([])
False
>>> 0 or 0.0 or "" or [] or {} or () or None or False or "All of them are false-y!"
'All of them are false-y!'
>>> "Hello, world!"
'Hello, world!'
>>> 'This is an AWESOME string!'
'This is an AWESOME string!'
>>> """This is a
... multiline "string" with quotes
... and that's totally fine
... """
"This is a\nmultiline string\nand that's totally fine\n"
>>> "I can put\nescape characters\nright in my code!"
'I can put\nescape characters\nright in my code!'
>>> u"Unicodeは素晴らしいです"
u'Unicode\u306f\u7d20\u6674\u3089\u3057\u3044\u3067\u3059'
>>> u"Unicodeは素晴らしいです".encode("utf-8")
'Unicode\xe3\x81\xaf\xe7\xb4\xa0\xe6\x99\xb4\xe3\x82\x89\xe3\x81\x97\xe3\x81\x84\xe3\x81\xa7\xe3\x81\x99'
>>> "abc" + "123"
'abc123'
>>> ("simple " "automatic " "concatenation")
'simple automatic concatenation'
>>> ", ".join(["abc", "def", "ghi"])
'abc, def, ghi'
>>> "My name is: %s and I am %d years old" % ("Jimbo", 17)
'My name is: Jimbo and I am 17 years old'
>>> "My name is {name} and I am {age} years old".format(name="Jimbo", age=17)
'My name is Jimbo and I am 17 years old'
>>> "this is just a test".split()
['this', 'is', 'just', 'a', 'test']
>>> "nan" * 17 + " Batman!"
'nannannannannannannannannannannannannannannannannan Batman!'
>>> [1, 2, 3, 4]
[1, 2, 3, 4]
>>> ["Sally", "Dick", "Jane"]
['Sally', 'Dick', 'Jane']
>>> [1, "John", True]
[1, 'John', True]
>>> [[1, 2], [3, 4], [5, 6]]
[[1, 2], [3, 4], [5, 6]]
>>> a = []
>>> a.append(1)
>>> a
[1]
>>> a.append(2)
>>> a
[1, 2]
>>> a + [3, 4]
[1, 2, 3, 4]
>>> a
[1, 2]
>>> a += [3, 4]
>>> a
[1, 2, 3, 4]
>>> names = ["Tom", "Dick", "Sally", "Jane"]
>>> names.index("Sally")
2
>>> names.index("foobar")
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: 'foobar' is not in list
>>> names[2]
'Sally'
>>> names[len(names)-1]
'Jane'
>>> names[-1]
'Jane'
>>> names[-2]
'Sally'
>>> names = ["Tom", "Dick", "Sally", "Jane"]
>>> names[0:2]
['Tom', 'Dick']
>>> names[1:2]
['Dick']
>>> names[2:2]
[]
>>> names[:2]
['Tom', 'Dick']
>>> names[2:len(names)]
['Sally', 'Jane']
>>> names[2:]
['Sally', 'Jane']
>>> names[::2]
['Tom', 'Sally']
>>> names[1::2]
['Dick', 'Jane']
>>> phrase = "I am the Real Slim Shady!"
>>> phrase[0]
'I'
>>> phrase[-1]
'!'
>>> phrase[0:4]
'I am'
>>> phrase[::2]
'Ia h elSi hd!'
>>> phrase[1::2]
' mteRa lmSay'
>>> phrase[::-1]
'!ydahS milS laeR eht ma I'
>>> [1, 2, 3, 4][::-1]
[4, 3, 2, 1]
>>> {}
{}
>>> {"name": "Jimbo", "age": 17}
{'age': 17, 'name': 'Jimbo'}
>>> dude = {"name": "Jimbo", "age": 17}
>>> dude["name"]
'Jimbo'
>>> dude["age"]
17
>>> dude["height"] = 183 # cm
>>> dude["height"]
183
>>> dude
{'age': 17, 'name': 'Jimbo', 'height': 183}
>>> del dude["age"]
>>> dude
{'name': 'Jimbo', 'height': 183}
>>> a = {}
>>> "mk" in a
False
>>> b = {"mk": 123}
>>> "mk" in b
True
>>> a["mk"]
Traceback (most recent call last):
File "<input>", line 1, in <module>
KeyError: 'mk'
>>> a.get("mk")
>>> print a.get("mk")
None
>>> a.get("mk", 1234)
1234
>>> a = {"foo": 1, "bar": 2}
>>> b = {"bar": 3, "baz": 4}
>>> a.update(b)
>>> a
{'baz': 4, 'foo': 1, 'bar': 3}
>>> b
{'baz': 4, 'bar': 3}
A "mutable" data type can be updated in place after it has been fully initialized. Update operations that modify the internal state of an object are said to be "mutating" the object.
An "immutable" data type cannot be modified after construction. Since these values cannot be updated directly, your only option is to generate new values by copying part or all of an existing value.
Mutable data types do not have a stable hashing algorithm since their internal state could change therefore changing the resulting hash value.
Immutable data types never change after construction, therefore their hash value will never change. All builtin immutable data types in Python are said to be "hashable"
Only hashable objects can be used as keys in dicts or elements of sets. For a collection type to be hashable, all elements must be hashable, recursively.
Examples of mutable data types include lists, dicts, and most kinds of user-defined objects.
Examples of immutable data types include numbers (ints, floats), strings, and tuples.
>>> d = {}
>>> d["John Jameson"] = 123
>>> d[("Foo", (1, 2))] = 456
>>> d[{"error": "incoming"}] = None
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> s = set()
>>> s.add(1)
>>> s
set([1])
>>> s.add(1)
>>> s
set([1])
>>> s.add([1, 2, 3])
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> (1, 2, 3, 4)
(1, 2, 3, 4)
>>> ("a", "b", 1, 2, 3)
('a', 'b', 1, 2, 3)
>>> a = (1, 2, 3)
>>> a[0] = 4
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> {("jason", 1): 1, ("adam", 1): 1}
{('adam', 1): 1, ('jason', 1): 1}
>>> {["jason", 1]: 1, ["adam", 1]: 1}
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'
*Pronounced "too-pul" not "tuh-pl"
>>> a = set([1, 1, 1, 2, 2, 3])
>>> a
set([1, 2, 3])
>>> a.add(4)
>>> a
set([1, 2, 3, 4])
>>> b = set([3, 4, 5, 6])
>>> a.union(b)
set([1, 2, 3, 4, 5, 6])
>>> a.intersection(b)
set([3, 4])
>>> a | b
set([1, 2, 3, 4, 5, 6])
>>> a & b
set([3, 4])
>>> set([1, 2, 3]).issubset(set([1, 2, 3, 4, 5]))
True
>>> a = {1, 2, 3, 4}
>>> b = {4, 5, 6, 7}
>>> a.difference(b)
set([1, 2, 3])
>>> b.difference(a)
set([5, 6, 7])
>>> a.symmetric_difference(b)
set([1, 2, 3, 5, 6, 7])
>>> a.add(["foo", "bar"])
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> a.add(("foo", "bar"))
>>> a
set([('foo', 'bar'), 1, 2, 3, 4])
Note: Based on dict internally; same restrictions apply.
>>> n = 0
>>> a, b = 1, 2
>>> a
1
>>> b
2
>>> a, b = (3, 4)
>>> a
3
>>> b
4
>>> a, b = [5, 6]
>>> a
5
>>> b
6
>>> a, b, c = 1, 2
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: need more than 2 values to unpack
Source: https://docs.python.org/2/library/stdtypes.html
Source: https://docs.python.org/2/library/stdtypes.html
Source: https://docs.python.org/2/library/stdtypes.html
Source: https://docs.python.org/2/library/stdtypes.html
>>> a = [1, 2, 3]
>>> if 5 in a:
... print "Yay!"
>>> if 2 in a:
... print "Awesome!"
...
Awesome!
>>> if 5 in a:
... print "That's my favorite number!"
... else:
... print "Awww schucks!"
...
Awww schucks!
>>> if 5 in a:
... print "That's my favorite number!"
... elif 4 in a:
... print "Well, that's second best!"
... elif 3 in a:
... print "Honestly not a fan."
... else:
... print "Awww schucks!"
...
Honestly not a fan.
>>> n = 0
>>> while n < 5:
... print n
... n += 1
...
0
1
2
3
4
>>> while True:
... # Warning, infinite loop
... print "Python is neat!"
...
Python is neat!
Python is neat!
Python is neat!
Python is neat!
HeatDeathOfUniverseError: program terminated due to universal heat death
>>> for i in [1, 2, 3]:
... print i
...
1
2
3
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in range(5):
... print i
...
0
1
2
3
4
>>> name = ["Tom", "Dick", "Jane"]
>>> for i in range(len(name)):
... print i, name[i]
...
0 Tom
1 Dick
2 Jane
>>> for n in [1, 3, 5, 6, 7, 9]:
... if n % 2 == 0:
... print "found an even!", n
... break
... else:
... print "odd", n
...
odd 1
odd 3
odd 5
found an even! 6
>>> for n in [1, 2, 3, 5, 6, 7, 9]:
... if n % 2 == 0:
... continue
... print "found an odd number!", n
...
found an odd number! 1
found an odd number! 3
found an odd number! 5
found an odd number! 7
found an odd number! 9
>>> range(2, 5)
[2, 3, 4]
>>> range(5, 5)
[]
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
Source: https://docs.python.org/2/tutorial/controlflow.html#for-statements
>>> for i in range(10):
... pass
...
>>> for i in range(10):
... if i % 2 == 0:
... pass
... print "num", i
...
num 0
num 1
num 2
num 3
num 4
num 5
num 6
num 7
num 8
num 9
(aka the great "tab vs space" debate)
Python code features syntactically significant whitespace. This means that code blocks are delimited by indent level rather than by delimiting characters such as { } (as in C/C++) or "being .. end".
Significant whitespace leads to cleaner code overall, and reduces block nesting ambiguity present in other languages.
Multi-line statements such a def, if, for, while, and class (among others) end in ":" followed by at least one line with an increased indent-level. pass can be used as a trivial place holder statement.
>>> range(2, 5)
[2, 3, 4]
>>> range(5, 5)
[]
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
Source: https://docs.python.org/2/tutorial/controlflow.html#for-statements
Python has a formal RFC process to introduce changes into the language or ecosystem. "Python Enhancement Proposals", or PEPs, cover a huge variety of topics and proposals, each of which undergo rigorous community discussion and debate before being accepted.
PEP8 is the official Python style guide. It describes the syntactic and stylistic idioms used by the Python core team and the broader Open Source ecosystem. Most projects adhere to PEP8, and many won't accept contributions that violate PEP8 standards.
>>> def simple():
... print "Hello, world!"
...
>>> simple()
Hello, world!
>>> def add_one(n):
... return n + 1
...
>>> add_one(5)
6
>>> def add(a, b):
... return a + b
...
>>> add(1, 2)
3
>>> def square(n):
... return n * n
...
>>> def squares(start, end):
... for n in range(start, end):
... print square(n)
...
>>> squares(2, 6)
4
9
16
25
>>> def say_hello(name="Michael-Keith"):
... print "Hello there, {}".format(name)
...
>>> say_hello()
Hello there, Michael-Keith
>>> say_hello("Bryant")
Hello there, Bryant
>>> def say_hello_a_lot(n, name="Michael-Keith"):
... for i in range(n):
... print "Hello there, {}".format(name)
...
>>> say_hello_a_lot(3)
Hello there, Michael-Keith
Hello there, Michael-Keith
Hello there, Michael-Keith
>>> say_hello_a_lot(3, "Bryant")
Hello there, Bryant
Hello there, Bryant
Hello there, Bryant
>>> say_hello_a_lot()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: say_hello_a_lot() takes at least 1 argument (0 given)
>>> def say_hello_a_lot(n=3, name="Fess"):
... for i in range(n):
... print "Hello there, {}".format(name)
...
>>> say_hello_a_lot()
Hello there, Fess
Hello there, Fess
Hello there, Fess
>>> say_hello_a_lot(name="Wes")
Hello there, Wes
Hello there, Wes
Hello there, Wes
>>> say_hello_a_lot(name="Brian", n=2)
Hello there, Brian
Hello there, Brian
>>> say_hello_a_lot(4, "Ken")
Hello there, Ken
Hello there, Ken
Hello there, Ken
Hello there, Ken
>>> def greet_peoples(*names):
... for name in names:
... print "Hello there, {}".format(name)
...
>>> greet_peoples()
>>> greet_peoples("Vic")
Hello there, Vic
>>> greet_peoples("Yuri", "Naga")
Hello there, Yuri
Hello there, Naga
>>> def greet_peoples_a_lot(n, *names):
... for name in names:
... for i in range(n):
... print "Hello there, {}".format(name)
...
>>> greet_peoples_a_lot(2, "Henry", "Joseph")
Hello there, Henry
Hello there, Henry
Hello there, Joseph
Hello there, Joseph
>>> def kwargs_test(**kwargs):
... return kwargs
...
>>> kwargs_test(foo=1, bar=2, baz=3)
{'baz': 3, 'foo': 1, 'bar': 2}
>>> def describe_stuff(**kwargs):
... for k in kwargs:
... print "Who are we kidding? {} is {}!".format(k, kwargs[k])
...
>>> describe_stuff(python="awesome", frank="Ken")
Who are we kidding? python is awesome!
Who are we kidding? frank is Ken!
>>> names = ["Jane", "Dick", "Sally"]
>>> def greet_peoples(*names):
... for name in names:
... print "Hello there, {}".format(name)
...
>>> greet_peoples(*names)
Hello there, Jane
Hello there, Dick
Hello there, Sally
>>> things = {"python": "awesome", "frank": "ken"}
>>> def describe_stuff(**kwargs):
... for k in kwargs:
... print "Who are we kidding? {} is {}!".format(k, kwargs[k])
...
>>> describe_stuff(**things)
Who are we kidding? python is awesome!
Who are we kidding? frank is ken!
Mix-and-match positional arguments, keyword arguments, *args, and **kwargs!
Everything in Python is an object. An object is composed of 4 ideas:
The identity of an object is the property that distinguishes it from other objects in the system. Identity is consistent over time, even if the object's state evolves. Many objects in the system will have distinct identities while having similar internal state.
>>> a = []
>>> b = []
>>> (id(a), id(b))
(4554702144, 4554544408)
>>> a += [1, 2, 3]
>>> b += [1, 2, 3]
>>> (id(a), id(b))
(4554702144, 4554544408)
>>> a == b
True
>>> a is b
False
The state of an object is defined as the contents of its attributes or fields at a point in time. Immutable objects have a fixed state for all points in time after their initialization. Mutable objects can have different state at different points in time.
>>> a = []
>>> a
[]
>>> a += [1, 2, 3]
>>> a
[1, 2, 3]
>>> a += [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
Behavior is the set of valid transformations that can be applied to an object. Some behaviors may mutate the object's internal state, while others may produce new derivative objects. Functions and methods provide the behavioral aspects of the object model.
>>> a = [1, 2, 3]
>>> len(a)
3
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b = {"foo": "bar"}
>>> b
{'foo': 'bar'}
>>> del b["foo"]
>>> b
{}
Types define the initialization process, behavior, and state structure of an object. Types are used by the runtime to enforce invariants about the construction and usage of objects. Types can be arranged in arbitrary abstract hierarchies using inheritance.
>>> a = [1, 2 ,3]
>>> b = {"foo": "bar"}
>>> type(a)
<type 'list'>
>>> type(b)
<type 'dict'>
>>> a + [1, 2, 3]
[1, 2, 3, 1, 2, 3]
>>> a + b
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: can only concatenate list (not "dict") to list
If you forget everything the previous 5 slides said, remember only the following 3 points:
*A value is "first-class" if it can be used like most other values in the system. In practical terms, first-class values can be assigned to variables, passed to functions, returned from functions, etc.
Examples: ints, strings, lists, and functions!
>>> def add(a, b):
... return a + b
...
>>> add(1, 2)
3
>>> def add_sub(a, b):
... return (a + b, a - b)
...
>>> add_sub(1, 2)
(3, -1)
>>> added, subbed = add_sub(1, 2)
>>> added
3
>>> subbed
-1
>>> def add(a, b):
... return a + b
...
>>> add(1, 2)
3
>>> def apply_op(op, a, b):
... return op(a, b)
...
>>> apply_op(add, 1, 2)
3
>>> def sub(a, b):
... return a - b
...
>>> apply_op(sub, 1, 2)
-1
>>> def apply_many_ops(a, b, **ops):
... for k in ops:
... print "{} {} {} = {}".format(a, k, b, ops[k](a, b))
...
>>> apply_many_ops(1, 2, plus=add, subtract=sub)
1 subtract 2 = -1
1 plus 2 = 3
A higher-order function is a function that operates on other functions in one or both of the following ways:
apply_op in the previous example was a higher-order function because it accepted a function (the operator to be applied) as an argument along with a and b.
>>> def add(a, b):
... return a + b
...
>>> def apply_op(op, a, b):
... return op(a, b)
...
>>> apply_op(add, 1, 2)
3
>>> def add(a, b):
... return a + b
...
>>> add(1, 2)
3
>>> add = lambda a, b: a + b
>>> add(1, 2)
3
>>> def apply_op(op, a, b):
... return op(a, b)
...
>>> apply_op(lambda x, y: x + y, 10, 20)
30
>>> def add(a, b):
... return a + b
...
>>> def print_arguments(fn):
... def _wrapper(*args, **kwargs):
... res = fn(*args, **kwargs)
... print "Called {} with args {} and kwargs {}. Returned {}".format(
... fn.func_name, args, kwargs, res)
... return res
... return _wrapper
...
>>> print_arguments(add)
<function _wrapper at 0x10f7bd0c8>
>>> wrapped_add = print_arguments(add)
>>> wrapped_add(1, 2)
Called add with args (1, 2) and kwargs {}. Returned 3
3
>>> add(1, 2)
3
>>> def print_arguments(fn):
... def _wrapper(*args, **kwargs):
... res = fn(*args, **kwargs)
... print "Called {} with args {} and kwargs {}. Returned {}".format(
... fn.func_name, args, kwargs, res)
... return res
... return _wrapper
...
>>> @print_arguments
... def add(a, b):
... return a + b
...
>>> add(1, 2)
Called add with args (1, 2) and kwargs {}. Returned 3
3
# @foo
# @bar
# def my_fn():
# pass
#
# is equivalent to
#
# def my_fn():
# pass
# my_fn = foo(bar(my_fn))
>>> def nat():
... nums = []
... num = 0
... while True:
... nums.append(num)
... num += 1
... return nums
...
>>> nat()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 5, in nat
KeyboardInterrupt
>>> def nat():
... n = 0
... while True:
... yield n
... n += 1
...
>>> nums = nat()
>>> next(nums)
0
>>> next(nums)
1
>>> next(nums)
2
>>> nums = [1, 2, 3, 4]
>>> def inc_nums(nums):
... res = []
... for num in nums:
... res.append(num + 1)
... return res
...
>>> inc_nums(nums)
[2, 3, 4, 5]
>>> [n + 1 for n in nums]
[2, 3, 4, 5]
>>> squares = [n ** 2 for n in range(10)]
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> nums = [1, 2, 3]
>>> def pairs(l1, l2):
... res = []
... for e1 in l1:
... for e2 in l2:
... res.append((e1, e2))
... return res
...
>>> pairs(nums, nums)
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
>>> [(e1, e2) for e1 in nums for e2 in nums]
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
>>> [(e1, e2) for e1 in nums for e2 in nums if e1 != e2]
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
>>> names = ["Tom", "Dick", "Sally"]
>>> for i in range(len(names)):
... print i, names[i]
...
0 Tom
1 Dick
2 Sally
>>> for i, name in enumerate(names):
... print i, name
...
0 Tom
1 Dick
2 Sally
>>> d = {"foo": "bar", "spam": "eggs"}
>>> for k in d:
... print "k: {}, v: {}".format(k, d[k])
...
k: foo, v: bar
k: spam, v: eggs
>>> for k, v in d.iteritems():
... print "k: {}, v: {}".format(k, d[k])
...
k: foo, v: bar
k: spam, v: eggs
>>> d = {"foo": "bar", "spam": "eggs"}
>>> for k in d:
... print "k: {}, v: {}".format(k, d[k])
...
k: foo, v: bar
k: spam, v: eggs
>>> for k, v in d.iteritems():
... print "k: {}, v: {}".format(k, d[k])
...
k: foo, v: bar
k: spam, v: eggs
>>> 1 / 0
Traceback (most recent call last):
File "<input>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> try:
... 1 / 0
... except:
... print "Mistakes were made"
...
Mistakes were made
>>> def blow_up():
... 1 / 0
...
>>> blow_up()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 2, in blow_up
ZeroDivisionError: integer division or modulo by zero
>>> try:
... 1 / 0
... except ZeroDivisionError:
... print "Thats not even a number!"
...
Thats not even a number!
>>> try:
... 1 / 0
... except KeyError:
... print "This won't be executed"
...
Traceback (most recent call last):
File "<input>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> try:
... 1 / 0
... except KeyError:
... print "How would you get here?"
... except ZeroDivisionError:
... print "Fix your math!"
...
Fix your math!
>>> try:
... 1 / 0
... except ZeroDivisionError as exc:
... print "I blew up because of {}".format(exc)
...
I blew up because of integer division or modulo by zero
>>> try:
... 1 / 0
... except Exception as e:
... print "Failed because of {}".format(e)
...
Failed because of integer division or modulo by zero
# Note: ZeroDivisionError is a subclass of Exception (as are all exceptions)
>>> try:
... 1 / 0
... except:
... print "I died"
... finally:
... print "Run me no matter what"
...
I died
Run me no matter what
>>> try:
... 1 + 1
... except:
... print "I died"
... finally:
... print "Run me no matter what"
...
2
Run me no matter what
>>> try:
... 1 / 0
... except:
... print "Thing have gone poorly"
... raise
...
Thing have gone poorly
Traceback (most recent call last):
File "<input>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> try:
... raise ValueError("This is not the right thing")
... except:
... print "Try to recover!"
...
Try to recover!
Python borrows the core of its Object Oriented Programming model from other classically OOP languages like Java and C++.
Warning: Object Oriented Programming is a complex topic that warrants a talk of its own. OOP is rarely worth the added mental and technical complexity for new programmers.
If you're generally new to programming, skip OOP until you feel more comfortable with language fundamentals.
>>> class User(object):
... def __init__(self, first_name, last_name, email):
... self.first_name = first_name
... self.last_name = last_name
... self.email = email
...
... def say_hello(self):
... print "{} says hello!".format(self.first_name)
...
... @property
... def full_name(self):
... return " ".join([self.first_name, self.last_name])
...
>>> u = User("John", "Smith", "jsmith@example.com")
>>> u.first_name
'John'
>>> u.last_name
'Smith'
>>> u.email
'jsmith@example.com'
>>> u.full_name
'John Smith'
>>> u.say_hello()
John says hello!
>>> type(u)
<class '__main__.User'>
>>> abs(1)
1
>>> abs(-1)
1
>>> nums = [1, 3, 5, 6]
>>> any(e % 2 == 0 for e in nums)
True
>>> all(e % 2 == 0 for e in nums)
False
>>> int("1337")
1337
>>> float("1337")
1337.0
>>> float("1337.1337")
1337.1337
>>> max(nums)
6
>>> max(["Tom", "Jane", "Albert"], key=len)
'Albert'
>>> min(["Tom", "Jane", "Albert"], key=len)
'Tom'
>>> nums = range(5)
>>> nums
[0, 1, 2, 3, 4]
>>> sorted(nums)
[0, 1, 2, 3, 4]
>>> sorted(nums, reverse=True)
[4, 3, 2, 1, 0]
>>> sum(nums)
10
>>> names = ["Tom", "Jane", "Albert"]
>>> reversed(names)
<listreverseiterator object at 0x10880d410>
>>> list(reversed(names))
['Albert', 'Jane', 'Tom']
>>> names[::-1]
['Albert', 'Jane', 'Tom']
>>> zip(names, nums)
[('Tom', 0), ('Jane', 1), ('Albert', 2)]
>>> dict(zip(names, nums))
{'Jane': 1, 'Albert': 2, 'Tom': 0}
Python has a massive standard library that has tools for virtually every common workload. There are over 287 modules in the standard library as of Python 2.7.9.
A selection of interesting modules in the standard lib:
Python is one of the most popular languages in the world. Its wealth of Free and Open Source code is what makes it so attractive. Libraries you should check out:
Python has made many trade-offs, some of which are more important than others, but they're worth noting:
Python 3 has been in development since 2008. That last official version of Python 2 is 2.7. No official feature development will be done on 2.x apart from bug fixes and security patches. This decision was made to help increase adoption for Python 3.x
Adoption for 3.x has been very slow due to the severe backwards incompatibilities it introduces. As a result, the vast majority of libraries are still written for 2.x first, then ported to 3.x. 2.x is the most popular version of Python today.
Is Python 3.x the right choice for me?
For many workloads, Python 2.x is still the best option. Especially for scripting or ops-related work, I suggest Python 2.x
Hopefully you now have an overview of what Python is capable of, and enough knowledge to be able to read and write basic applications.
Additional Resources:
Thanks for listening! Questions?