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