def square(x): return mul(x, x) def sum_squares(x, y): return square(x) + square(y)
sum_squares need to know about
squaretakes one argument.
squarecomputes the square of a number.
sum_squares not need to know about
squarehas the intrinsic name
squarecomputes the square by calling
def square(x): def square(x): return pow(x, 2) return mul(x, x-1) + x
square were bound to a built-in function,
sum_squares would still work identically. The mechanisms of
square are irrelevant to
Names should convey the meaning or purpose of the values to which they are bound. The type of value bound to the name is best documented in a function's docstring.
Function names typically convey their effect (
triple), or the value returned (
Any of the following reasons makes it fair to add a new name:
if sqrt(square(a) + square(b)) > 1: x = x + sqrt(square(a) + square(b)) # avoid repeating sqrt(square(a) + square(b)) hypotenuse = sqrt(square(a) + square(b)) if hypotenuse > 1: x = x + hypotenuse
x1 = (-b + sqrt(square(b) - 4 * a * c)) / (2 * a) # make the quadratic formula easier to discern discriminant = square(b) - 4 * a * c x1 = (-b + sqrt(discriminant)) / (2 * a)
average_age = average(age, students)is preferable to
aa = avg(a, st).
n, k, iare usually integers
x, y, zare usually real numbers
f, g, hare usually functions
Will get back to this.
The following is a giant example that takes everything learned so far into account. This is the remainder of today's lecture.
from wave import open from struct import Struct from math import floor, sin frame_rate = 11025 def encode(x): """Encode float x between -1 and 1 as two bytes. """ i = int(16384 * x) return Struct('h').pack(i) def play(sampler, name='song.wav', seconds=2): """Write the output of a sampler function as a wav file. """ out = open(name, 'wb') out.setnchannels(1) out.setsampwidth(2) out.setframerate(frame_rate) t = 0 while t < seconds * frame_rate: sample = sampler(t) out.writeframes(encode(sample)) t = t + 1 out.close() def tri(frequency, amplitude=0.3): """A continuous triangle wave.""" period = frame_rate // frequency def sampler(t): saw_wave = t / period - floor(t / period + 0.5) tri_wave = 2 * abs(2 * saw_wave) - 1 return amplitude * tri_wave return sampler c_freq, e_freq, g_freq = 261.63, 329.63, 392.00 # play(tri(c_freq)) c = tri(c_freq) e = tri(e_freq) g = tri(g_freq) low_g = tri(g_freq/2) def both(f, g): return lambda t: f(t) + g(t) # play(both(c, e)) # play(both(c, both(e, g))) # play(both(c, both(e, g)), seconds=1) def note(f, start, end, fade=.1): def sampler(t): seconds = t / frame_rate if seconds < start or seconds > end: return 0 elif seconds < start + fade: return (seconds - start) / fade * f(t) elif seconds > end - fade: return (end - seconds) / fade * f(t) else: return f(t) return sampler # play(note(c, 0, 1/4)) # play(both(note(c, 0, 1/4), # note(e, 1/2, 1))) def mario(c, e, g, low_g): z = 0 song = note(e, z, z + 1/8) z += 1/8 song = both(song, note(e, z, z + 1/8)) z += 1/4 song = both(song, note(e, z, z + 1/8)) z += 1/4 song = both(song, note(c, z, z + 1/8)) z += 1/8 song = both(song, note(e, z, z + 1/8)) z += 1/4 song = both(song, note(g, z, z + 1/4)) z += 1/2 song = both(song, note(low_g, z, z + 1/4)) return song def mario_at(octave): c = tri(c_freq * octave) e = tri(e_freq * octave) g = tri(g_freq * octave) low_g = tri(g_freq/2 * octave) return mario(c, e, g, low_g) play(both(mario_at(1), mario_at(0.5)))