-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3_functions.py
More file actions
157 lines (112 loc) · 3.33 KB
/
3_functions.py
File metadata and controls
157 lines (112 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
'''
Functions
'''
def foo(x):
'''
This function computes the square of x.
'''
return x**2
print(foo(10))
help(foo) # Display the doc string.
def foo(x): # Functions can return multiple values
return x**2, x**4, x**8
print(foo(10))
print(type(foo(10)))
x2, x4, x8 = foo(10) # Tuple unpacking!
def foo(x): # Returns None when nothing is returned
pass
print(foo(10))
def foo(argument1, argument2): # Functions can take many input arguments
return argument1**argument2
print(foo(2, 4))
def raise_x(exponent, x=2): # With one default argument.
return x**exponent
print(raise_x(8))
print(raise_x(8, x=8)) # Overwrite default value
print(raise_x(x=7, exponent=8))
print(raise_x(7, 8))
# *args and **kwargs
def foo(x,y):
return x*y
print(foo(3,4))
print(foo(3,4,2))
# With *args you can create more flexible code that accepts a varied amount of non-keyworded arguments within your function:
def foo(*args):
print(args)
print(foo(3,4,2))
def foo(*args):
z = 1
for num in args:
z *= num
return z
print(foo(3,4,2))
def foo(base, *args): # possible to combine normal arguments with *args
return [base**a for a in args]
foo(2, 1, 2, 3, 4)
# **kwargs works the same, but now one has to provide keywords.
def foo(*args, **kwargs):
print(args)
print(kwargs)
foo(1, 2, 3, key1='value', key2='value2')
# Do something more fancy: Print a spiral to the console
# and use two functions for this.
def spiral_distance(x, y, alpha=5, beta=2, max_dist=100):
'''
Return distance to closest spiral arm
'''
from math import atan2, pi
r = (x**2 + y**2)**.5
theta = atan2(y, x)
distance = min(
[abs((r - (alpha + beta * theta + rev * beta * pi * 2)))
for rev in range(0, max_dist)])
return distance
def print_spiral(nx, ny, dt=0.5, **kw):
for x in range(-nx, nx):
for y in range(-nx, ny):
r = spiral_distance(x, y, **kw)
if r < dt:
print('# ', end='')
else:
print('_ ', end='')
print('')
print_spiral(10, 10, dt=1, beta=1, alpha=0,)
print_spiral(10, 10, dt=1, beta=1, alpha=0, max_dist=2)
# Functions are objects
foo = print_spiral
foo(10, 10, dt=1, beta=1, alpha=0)
# This enables several really nice things:
def print_distance(func, nx, ny, dt=0.5, **kw):
for x in range(-nx, nx):
for y in range(-nx, ny):
r = func(x, y, **kw)
if r < dt:
print('# ', end='')
else:
print('_ ', end='')
print('')
print_distance(spiral_distance, 10, 10)
# Simple functions:
foo = lambda x,y: spiral_distance(x, y, beta=0.5)
print_distance(foo, 10, 10, dt=1)
# But also the following pattern:
def log(func):
def foo(*args, **kw):
print('Calling function', func.__name__)
return func(*args, **kw)
return foo
print_distance = log(print_distance)
print_distance(spiral_distance, 10, 10)
# This is called the decorator pattern and there is
# some syntax sugar for it:
@log
def print_distance(func, nx, ny, dt=0.5, **kw):
for x in range(-nx, nx):
for y in range(-nx, ny):
r = func(x, y, **kw)
if r < dt:
print('# ', end='')
else:
print('_ ', end='')
print('')
print_distance(spiral_distance, 10, 10)