In [1]:
def sagan():
quote = "With insufficient data it is easy to go wrong."
In [2]:
def null():
pass
In [3]:
# define the function
def forty_two():
return 42
In [4]:
# call the function
forty_two()
Out[4]:
In [5]:
# call the function, and print the result
print(forty_two())
In [6]:
# call the function, assign the result
# to x, and print x
x = forty_two()
print(x)
In [7]:
def forty_two_or_bust(x):
if x:
print(42)
else:
print(0)
In [8]:
# call the function
forty_two_or_bust(True)
In [9]:
bust = False
forty_two_or_bust(bust)
In [10]:
def power(base, x):
return base**x
In [11]:
from math import sin
def sin_inv_x(x):
if x == 0.0:
result = 0.0
else:
result = sin(1.0/x)
return result
In [12]:
def power(base, x):
"""Computes base^x. Both base and x should be integers,
floats, or another numeric type.
"""
return base**x
In [13]:
def line(x, a=1.0, b=0.0):
return a*x + b
In [14]:
line(42) # no keyword args, returns 1*42 + 0
Out[14]:
In [15]:
line(42, 2) # a=2, returns 84
Out[15]:
In [16]:
line(42, b=10) # b=10, returns 52
Out[16]:
In [17]:
line(42, b=10, a=2) # returns 94
Out[17]:
In [18]:
line(42, a=2, b=10) # also returns 94
Out[18]:
In [19]:
# Do not do this!
def myappend(x, lyst=[]):
lyst.append(x)
return lyst
In [20]:
myappend(6) # seems right
Out[20]:
In [21]:
myappend(42) # hmmm...
Out[21]:
In [22]:
myappend(12, [1, 16])
Out[22]:
In [23]:
myappend(65) # nope, not right!
Out[23]:
In [24]:
def myappend(x, lyst=None):
if lyst is None:
lyst = []
lyst.append(x)
return lyst
In [25]:
myappend(6)
Out[25]:
In [26]:
myappend(42)
Out[26]:
In [27]:
myappend(12, [1, 16])
Out[27]:
In [28]:
myappend(65)
Out[28]:
In [29]:
max(6, 2)
Out[29]:
In [30]:
max(6, 42)
Out[30]:
In [31]:
max(1, 16, 12)
Out[31]:
In [32]:
max(65, 42, 2, 8)
Out[32]:
In [33]:
def minimum(*args):
"""Takes any number of arguments!"""
m = args[0]
for x in args[1:]:
if x < m:
m = x
return m
In [34]:
minimum(6, 42)
Out[34]:
In [35]:
data = [65, 42, 2, 8]
minimum(*data)
Out[35]:
In [36]:
def blender(*args, **kwargs):
"""Will it?"""
print(args, kwargs)
In [37]:
blender("yes", 42)
In [38]:
blender(z=6, x=42)
In [39]:
blender("no", [1], "yes", z=6, x=42)
In [40]:
t = ("no",)
d = {"mom": "ionic"}
blender("yes", kid="covalent", *t, **d)
In [41]:
def momentum_energy(m, v):
p = m * v
e = 0.5 * m * v**2
return p, e
In [42]:
# returns a tuple
p_e = momentum_energy(42.0, 65.0)
print(p_e)
In [43]:
# unpacks the tuple
mom, eng = momentum_energy(42.0, 65.0)
print(mom)
In [44]:
# global scope
a = 6
b = 42
def func(x, y):
# local scope
z = 16
return a*x + b*y + z
# global scope
c = func(1, 5)
In [45]:
# global scope
a = 6
b = 42
def outer(m, n):
# outer's scope
p = 10
def inner(x, y):
# inner's scope
return a*p*x + b*n*y
# outer's scope
return inner(m+1, n+1)
# global scope
c = outer(1, 5)
In [46]:
a = 6
def a_global():
print(a)
def a_local():
a = 42
print(a)
a_global()
a_local()
print(a)
In [47]:
a = "A"
def func():
# you cannot use the global 'a' because...
print("Big " + a)
# a local 'a' is eventually defined!
a = "a"
print("small " + a)
func()
In [48]:
a = "A"
def func():
global a
print("Big " + a)
a = "a"
print("small " + a)
func()
print("global " + a)
In [49]:
# DO NOT RUN THIS
#def func():
# func()
In [50]:
def fib(n):
if n == 0 or n == 1:
return n
else:
return fib(n - 1) + fib(n - 2)
In [51]:
import sys
sys.getrecursionlimit() # return the current limit
sys.setrecursionlimit(8128) # change the limit to 8128
In [52]:
# a simple lambda
lambda x: x**2
Out[52]:
In [53]:
# a lambda that is called after it is defined
(lambda x, y=10: 2*x + y)(42)
Out[53]:
In [54]:
# just because it is anonymous doesn't mean we can't give it a name!
f = lambda: [x**2 for x in range(10)]
f()
Out[54]:
In [55]:
# a lambda as a dict value
d = {'null': lambda *args, **kwargs: None}
In [56]:
# a lambda as a keyword argument f in another function
def func(vals, f=lambda x: sum(x)/len(x)):
f(vals)
In [57]:
# a lambda as a keyword argument in a function call
func([6, 28, 496, 8128], lambda data: sum([x**2 for x in data]))
In [58]:
nums = [8128, 6, 496, 28]
In [59]:
sorted(nums)
Out[59]:
In [60]:
sorted(nums, key=lambda x: x%13)
Out[60]:
In [61]:
def countdown():
yield 3
yield 2
yield 1
yield 'Blast off!'
In [62]:
# generator
g = countdown()
In [63]:
next(g)
Out[63]:
In [64]:
x = next(g)
print(x)
In [65]:
y, z = next(g), next(g)
print(z)
In [66]:
next(g)
In [67]:
for t in countdown():
if isinstance(t, int):
message = "T-" + str(t)
else:
message = t
print(message)
In [68]:
def square_plus_one(n):
for x in range(n):
x2 = x * x
yield x2 + 1
In [69]:
for sp1 in square_plus_one(3):
print(sp1)
In [70]:
# define a subgenerator
def yield_all(x):
for i in x:
yield i
# palindrome using yield froms
def palindromize(x):
yield from yield_all(x)
yield from yield_all(x[::-1])
# the above is equivalent to this full expansion:
def palindromize_explicit(x):
for i in x:
yield i
for i in x[::-1]:
yield i
In [71]:
def null(f):
"""Always return None."""
return
def identity(f):
"""Return the function."""
return f
def self_referential(f):
"""Return the decorator."""
return self_referential
In [72]:
@null
def nargs(*args, **kwargs):
return len(args) + len(kwargs)
In [73]:
def nargs(*args, **kwargs):
return len(args) + len(kwargs)
nargs = null(nargs)
In [74]:
def plus1(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs) + 1
return wrapper
In [75]:
@plus1
def power(base, x):
return base**x
power(4, 2)
Out[75]:
In [76]:
@plus1
@identity
@plus1
@plus1
def root(x):
return x**0.5
root(4)
Out[76]:
In [77]:
def plus_n(n):
def dec(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs) + n
return wrapper
return dec
In [78]:
@plus_n(6)
def root(x):
return x**0.5
root(4)
Out[78]:
In [79]:
max = plus1(max)