Suggestions for python 2
Edward Welbourne
eddy at vortigen.demon.co.uk
Tue Jan 18 19:28:47 EST 2000
OK, examples of useful generators.
All URLs below are relative to http://www.chaos.org.uk/~eddy/dev/toy/
including refs to assorted.py files.
Harder for me to construct because, in truth, the reason for generators
is that class is a generator; if folk are going to insist on having the
ability to reorganise what class is, it can best be met by providing for
things that can replace class in the class statement, instead of by
bodging the way class itself works. I should really try to illustrate
some of the meta-class notions that got discussed, but can't remember
them. The type-checked class machine in check.py is an example.
The example I've already given is of the sub-namespace or submodule:
this is simply a plain way of making the namespace of a module
hierarchical; instead of defining several modules and importing them
into one container module (in the same sense as os.path is a
sub-namespace of os), construct a lightweight submodule within the
module itself - hence the planetary example in python2.html (and see
object.html). For that, see initspace in python.py: examples of its use
abound once it's been defined; it constructs something lightweight,
simple and totally devoid of sophistication.
The planetary example could be extended, using generator classes with
well-chosen behaviours, to give lazy-lookup methods that compute derived
data from the given data, to deploy reflexes that ensure defining a
body's orbit gets the body added to the list of satellites of the
orbit's centre (used as orbit's base, below: bases needn't always be
read in the conventional way), etc.:
import python, math
python.gennie bodgen (python.fallbacks):
def __call__(self, *bases, **what): # self will be Body
what.update({ 'dict': { '__dict__': {} },
'__class__': self })
inst, wrap = apply(python.wrapped, bases, what)
wrap.__lookups__.insert(0, python.dictlook(wrap.__dict__))
wrap.__lookups__.insert(1, python.bequeath(self, wrap))
wrap.__lookups__.append(python.getatt(inst))
wrap.__init__()
return inst, wrap
bodgen Body:
def __init__(self):
self.satellites = []
# or use a smarter object sorting entries by orbital radius
self.name = self.__name__
def __setattr__(self, key, value):
if key == 'orbit':
self.__dict__['orbit'] = value
orbit.occupant = self
else: self.__dict__[key] = value
python.gennie orbgen (python.fallbacks):
def __call__(self, *bases, **what): # self will be Orbit
what.update({ 'dict': { '__dict__': {} },
'__class__': self })
inst, wrap = apply(python.wrapped, (), what)
wrap.__lookups__.insert(0, python.dictlook(wrap.__dict__))
wrap.__lookups__.insert(1, python.bequeath(self, wrap))
wrap.__lookups__.append(python.getatt(inst))
wrap.__init__(bases[0])
return inst, wrap
orbgen Orbit:
# Presumes it will be given centre as its one base
def __init__(self, centre):
self.centre = centre
# will have .occupant set to Body in whose suite it appears
# but not 'til after __init__
def __setattr__(self, key, value):
if key == 'radius':
self.__dict__['radius'] = value # making it possible to:
self.centre.satellites.append(self.occupant)
else: self.__dict__[key] = value
def __getattr__(self, key):
if key == 'omega': # orbital angular velocity
self.omega = 2 * math.pi / self.period
return self.omega
from units import * # units of measurement ... another story.
Body Sun:
"""The Sun: the star at the heart of the solar system."""
type = 'G2 V'
magnitude = 4.79
aliases = 'Sol',
Body Earth:
"""The blue planet, cradle of life."""
Orbit orbit (Sun):
"""How our home moves about."""
radius = 93 * mega * mile
period = 1 * year
eccentricity = .0167
Body Moon:
"""The main cause of our tides"""
Orbit orbit (Earth):
radius = .238855 * mega * mile
period = 27 * day + 8 * hour
eccentricity = .055
Body Mercury:
Orbit orbit (Sun):
radius = 57.9e9 * metre
period = .241 * year
eccentricity = .2056
# ...
and we can use all the usual machinery of classes to set up
lazily-evaluated functionality on Body and Orbit objects to, e.g.,
compute the scale of tides (though we'd need phase-of-orbit and
tilt-of-axis data to work out the actual values at given moments) and
other mechanical truths. (The above is loosely based on a real piece of
python 1.5 which also handles units of measurement and error bars on
data - but in which the data-entry is nothing like as neat.)
The attentive will see that python.gennie isn't the ideal tool for this
job: I designed it as a means to build class. I'd have to play with a
lot of generator classes like bodgen and orbgen before I'd know what to
replace python.gennie with ...
Here's another simple hierarchical namespace, making some use of ability
to refer to earlier names within the suite of a sub-object:
sub = python.initspace
sub Cosmos:
G = 66.720 * pico * metre**3 / kilogramme / second**2
Hubble = 2.5 * atto * Hertz
sub Quantum:
h = 662.6176e-36 * Joule * second
hbar = h / 2 / math.pi
sub Vacuum:
c = 299792458 * metre / second
mu0 = permeability = .4 * pi * micro * Henry / metre
Z0 = impedance = mu0 * c
epsilon0 = permittivity = 1 / Z0 / c
sub Thermal:
k = Boltzmann = 13.8054 * yocto * Joule / Kelvin
Stefan = 56.7032 * nano * Watt / (metre * Kelvin**2)**2
sub Planck:
impedance = Vacuum.impedance # arguably / 4 / pi
action = Quantum.h # maybe over 2 (or 4) pi
charge = pow(action / impedance, .5) # 8.27 positrons
speed = Vacuum.c
_Newton = Cosmos.G / speed**3 # time/mass; arguably / 4 / pi
momentum = pow(action / _Newton, .5) # a cat at about 7 mile/hour
length = pow(action * _Newton, .5)
mass, energy = momentum / speed, momentum * speed
time, arearate = length / speed, length * speed
current, magneton = charge / time, charge * arearate
force, acceleration = momentum / time, speed / time
temperature = energy / Thermal.k # very very hot
torque = energy
Although the last should really be implemented using a generator class
which lets one set some sub-set of the units: it then infers any others
you ask for from formulae such as those after the initial few.
Sorry, the examples of generators aren't as good as I'd have liked.
Eddy.
More information about the Python-list
mailing list