&
: bitwise AND
|
: bitwise OR
~
: bitwise negation^
: bitwise XOR
(exclusive OR)a >> n
: right-shift n
placesa << n
: left-shift n
placesdef _int32_to_bytes(i):
"""Convert an integer to four bytes in little-endian format."""
return bytes((i & 0xff,
i >> 8 & 0xff,
i >> 16 & 0xff,
i >> 24 & 0xff))
"""Computing Mandelbrot sets.
https://en.wikipedia.org/wiki/Mandelbrot_set
"""
import math
def mandel(real, imag):
"""The logarithm of number of iterations needed to determine whether a complex point is in the Mandelbrot set.
Args:
real: The real coordinate
imag: The imaginary coordinate
Returns:
An integer in the range 1-225.
"""
x = 0
y = 0
for i in range(1, 257):
# alternatively, (x**2 + y**2)
if (x*x + y*y) > 4.0:
break
xt = real + x*x - y*y
y = imag + 2.0 * x * y
x = xt
return int(math.log(i) * 256 / math.log(265)) - 1
def mandelbrot(size_x, size_y):
"""Make a Mandelbrot set image.
Args:
size_x: Image width
size_y: Image height
Returns:
A list of lists of integers in the range 0-255.
"""
return [
[
mandel((3.5 * x / size_x) - 2.5, (2.0 * y / size_y) - 1.0) for x in range(size_x)
] for y in range(size_y)
]
in shell:
>>> import fractal
>>> pixels = fractal.mandelbrot(448, 256) # produces list of list of integers
>>> import reprlib
>>> reprlib.repr(pixels)
>>> import bmp
>>> bmp.write_grayscale("~/mandel.bmp", pixels) # can view image by opening it in a browser
def dimensions(filename):
"""Determine the dimensions in pixels of a BMP image.
Args:
filename: The filename of a BMP file.
Returns:
A tuple containing two integers with the width and height in pixels.
Raises:
ValueError: If the file was not a BMP file.
OSError: If there was a problem reading the file.
"""
with open(filename, 'rb') as f:
magic = f.read(2)
if magic != b'BM':
raise ValueError("{} is not a BMP file".format(filename))
f.seek(18)
width_bytes = f.read(4) # returns a bytes object since the file was opened in binary mode
height_bytes = f.read(4)
return (_bytes_to_int32(width_bytes),
_bytes_to_int32(height_bytes))
def _bytes_to_int32(b):
"""Convert a bytes object containing four bytes into an integer."""
# NOTE: indexing into bytes object returns an integer
return b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
in shell:
>>> import bmp_reader
>>> bmp_reader.dimensions("~/mandel.bmp")
#=> (448, 256)
"If it looks like a file and reads like a file, then it's a file!"
def words_per_line(flo):
return [len(line.split()) for line in flo.readlines()]
with open("~/wasteland.txt", mode='rt', encoding='utf-8') as real_file:
wpl = words_per_line(real_file)
wpl
#=> [9, 8, 9, 9]
type(real_file)
#=> <class '_io.TextIOWrapper'>
from urllib.request import urlopen
with urlopen("http://sixty-north.com/c/t.txt") as web_file:
wpl = words_per_line(web_file)
wpl
#=> [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 7, 8, 14, 12, 8]
type(web_file)
#=> <class 'http.client.HTTPResponse'>
"""Demonstrate raiding a refrigerator.
(using a context manager)
"""
from contextlib import closing
class RefrigeratorRaider:
"""Raid a refrigerator"""
def open(self):
print("Open fridge door.")
def take(self, food):
print(f"Finding {food}...")
if food == 'deep fried pizza':
raise RuntimeError("Health warning!")
print(f"Taking {food}")
def close(self):
print("Close fridge door.")
### before refactor
# def raid(food):
# r = RefrigeratorRaider()
# r.open()
# r.take(food)
# r.close()
def raid(food):
with closing(RefrigeratorRaider()) as r:
r.open()
r.take(food)
# calling `r.close()` will result in an unnecessary call to `close`
in shell:
>>> from fridge import raid
>>> raid('bacon')
#=> Open fridge door.
#=> Finding bacon...
#=> Taking bacon
#=> Close fridge door.
>>>
>>> raid('deep fried pizza')
#=> Open fridge door.
#=> Finding deep fried pizza...
#=> raises exception with RuntimeError: 'Health warning!'
### use `closing` in `raid` which wraps object in context manager that
### always calls `close` method on wrapped object before exiting
>>> raid('deep fried pizza')
#=> Open fridge door.
#=> Finding deep fried pizza...
#=> Close fridge door.
#=> raises exception with RuntimeError: 'Health warning!'