From wiki.python.org:
Short version: Python 2.x is legacy, Python 3.x is the present and future of the language
In [1]:
import functools
import urllib
@functools.lru_cache(maxsize=32)
def get_pep(num):
'Retrieve text of a Python Enhancement Proposal'
resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
try:
with urllib.request.urlopen(resource) as s:
return s.read()
except urllib.error.HTTPError:
return 'Not Found'
In [2]:
for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
pep = get_pep(n)
print(n, len(pep))
get_pep.cache_info()
Out[2]:
In [3]:
@functools.lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print([fib(n) for n in range(16)])
In [4]:
fib.cache_info()
Out[4]:
In [5]:
from functools import singledispatch
@singledispatch
def fun(arg, verbose=False):
if verbose:
print("Let me just say,", end=" ")
print(arg)
To add overloaded implementations to the function, use the register() attribute of the generic function. It is a decorator, taking a type parameter and decorating a function implementing the operation for that type:
In [6]:
@fun.register(int)
def _(arg, verbose=False):
if verbose:
print("Strength in numbers, eh?", end=" ")
print(arg)
@fun.register(list)
def _(arg, verbose=False):
if verbose:
print("Enumerate this:")
for i, elem in enumerate(arg):
print(i, elem)
To enable registering lambdas and pre-existing functions, the register() attribute can be used in a functional form:
In [7]:
def nothing(arg, verbose=False):
print("Nothing.")
fun.register(type(None), nothing)
Out[7]:
In [8]:
fun("Hello, world.")
In [9]:
fun("test.", verbose=True)
In [10]:
fun(42, verbose=True)
In [11]:
fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
In [12]:
2 / 3
Out[12]:
Implicit:
In [ ]:
try:
v = {}['a']
except KeyError as e:
raise ValueError('failed')
Explicit:
In [ ]:
try:
v = {}['a']
except KeyError as e:
raise ValueError('failed') from e
Doesn't work in IPython
but I'm working on that:
and more.
In [14]:
from enum import Enum
class Mood(Enum):
funky = 1
happy = 3
def describe(self):
# self is the member here
return self.name, self.value
def __str__(self):
return 'my custom str! {0}'.format(self.value)
@classmethod
def favorite_mood(cls):
# cls here is the enumeration
return cls.happy
In [15]:
print(Mood.favorite_mood())
print(Mood.happy.describe())
str(Mood.funky)
Out[15]:
In [16]:
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
# universal gravitational constant (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
In [17]:
Planet.EARTH.value
Out[17]:
In [18]:
Planet.EARTH.surface_gravity
Out[18]:
In [19]:
import statistics
scores = [12, 13, 88, 12, 61, 32]
print(statistics.mean(scores))
print(statistics.stdev(scores))
print(statistics.mode(scores))
In [20]:
print(statistics.mode(range(5)))
In [21]:
import asyncio
@asyncio.coroutine
def greet_every_two_seconds_three_times():
for _ in range(3):
print('Hello World')
yield from asyncio.sleep(2)
loop = asyncio.get_event_loop()
loop.run_until_complete(greet_every_two_seconds_three_times())
In [22]:
import asyncio
@asyncio.coroutine
def compute(x, y):
print("Compute %s + %s ..." % (x, y))
yield from asyncio.sleep(1.0)
return x + y
@asyncio.coroutine
def print_sum(x, y):
result = yield from compute(x, y)
print("%s + %s = %s" % (x, y, result))
loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1, 2))
In [23]:
import asyncio
@asyncio.coroutine
def factorial(name, number):
f = 1
for i in range(2, number+1):
print("Task %s: Compute factorial(%s)..." % (name, i))
yield from asyncio.sleep(1)
f *= i
print("Task %s: factorial(%s) = %s" % (name, number, f))
tasks = [
asyncio.Task(factorial("A", 2)),
asyncio.Task(factorial("B", 3)),
asyncio.Task(factorial("C", 4))]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
In [24]:
yield from [1, 2, 'banana!']
In [28]:
def show_me_yield():
yield from range(2)
yield "Surprise!"
yield from sorted(range(2), reverse=True)
In [29]:
for value in show_me_yield():
print(value)
In [30]:
first, *rest = range(5)
In [31]:
first
Out[31]:
In [32]:
rest
Out[32]:
In [33]:
first, *middle, last = range(5)
In [34]:
middle
Out[34]:
In [35]:
last
Out[35]:
In [36]:
first, *middle, least_but_not_last, last = range(5)
In [37]:
least_but_not_last
Out[37]:
In [38]:
def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
print(a, b, c)
In [39]:
foo(1, 2, 3)
In [40]:
foo.__annotations__
Out[40]:
In [41]:
foo.__annotations__['a']
Out[41]:
In [25]:
!pip install pytest pytest-quickcheck
In [26]:
%%writefile test.py
import pytest
MAX_NUMBER = 4
@pytest.mark.randomize(min_num=0, max_num=MAX_NUMBER, ncalls=12)
def test_generate_adding_ints(i1: int, i2: int):
assert i1 + i2 <= 2 * MAX_NUMBER
In [27]:
!python -m pytest test.py