User’s Guide, Chapter 36: Clients and Weak References¶
This chapter explains some of the underlying aspects of
functioning that may be helpful for someone doing advanced work in
understanding how the system works.
It pays to have good references¶
I’ve mentioned several times indirectly or directly the concept of
music21 and it’s worth mentioning a bit what they are.
(Programmers with a lot of past experience outside
music21 can skim
or skip ahead)
A reference is a relationship between two objects that allow them to share information with each other on a short or longer term basis. There are several types. Let me give an analogy that might help separate them.
Suppose two people (let’s call them Jane and José – the names of two students who worked on
music21) meet at a conference mixer and discover they have a lot in common (“You like computer music analysis too?!”). They can chat about whatever they want at the mixer but after they leave, they have no way to communicate with each other. We’ll call that being in the same scope (the mixer) but having no reference.
On the other hand, say José and Jane exchange phone numbers and emails – now they’re able to ask each other anything at any time from here on out. I’ll call this having a normal reference (also called a hard reference) to each other.
Imagine a third scenario where they exchange their hotel phone numbers (okay, unrealistic in 2015, but bear with me). Now they can chat about anything for a limited amount of time, but if Jane comes back in a month and dials room 348, odds are, she won’t find José there (my travel budget isn’t that big). Maybe they figure it’s unlikely that they’ll be in the same place again. Or sometimes it’s good to have single-serving friends. In computer speak, they have weak references to each other.
It’s also possible that the references can be asymmetrical. Jane could have José’s permanent phone number, but José might only have Jane’s room number. In this case Jane has a hard reference to José but José only has a weak reference to Jane.
Most items in
music21 have no reference to each other; they can only
share information when we put them in the same scope (the mixer) and
introduce them to each other (e.g., statements such as
if x > y:).
On the other hand, some objects have hard references to other objects.
For instance, each
Note object has a hard reference to a
object. Any note can get its pitch through the
.pitch attribute. But
Pitch objects do not have hard references to their
If you have a
Pitch there’s no
.note attribute that lets it find
This seems like a design flaw, and in an ideal world, they would have
references to each other. Sometimes you have a variable, such as
which is a
Pitch and it’d be great to do
p.note to figure out
Note it belongs to. But there’s a general rule in designing
programs that’s worth following: it’s dangerous for two objects to have
references to each other. Why? Because each object takes up space in the
computer’s memory. At a certain point, operating systems need to free up
objects that no one is using any more (like when you close a program,
all that undo data tends to vanish). Operating systems know when an
object is no longer being used when there are no (hard) references to
p had a
.note attribute pointing to
n had a
.pitch attribute pointing to
p then they would never get deleted
even if they were no longer in use (this process is called “garbage
One way to get around this problem is through the use of weak
references. A weak reference, like someone’s room number, lets a object
communicate with another for a certain length of time, but not forever.
For a computer system, if
object1 has a weak reference to
object2, it says that
object1 would like to communicate with
object2 as long as possible, but that this relationship isn’t strong
enough to prevent
object2 from disappearing when nothing else needs
Notes and other objects have strong references to their
Duration objects, stored in the
.duration attribute, but
Duration objects only have weak references to their
objects. This makes sense: as long as the
Note exists, the
Duration had better be around, but once the
there’s no need to keep its
Some objects that are in a weak reference relationship to others include
Streams. Streams have hard references to their
notes – they can’t just have their notes disappearing unannounced! But
Notes only have weak references to the Streams that they are in.
There are many notes in a stream, but there’s only one duration on a
note. When there is a one-to-one relationship between two objects, the
object holding the hard reference is called, in
“client.” Thus in a Note/Duration relationship, the
Note is the
client of the Duration. The relationship name implies that the Duration
is there to serve the client, the Note. When there’s no client, the
Duration is off duty and can go home.
Weak references can be a bit of a pain to work with in Python compared
to some other languages such as Perl (but much easier than, say,
much as possible tries to hide its weak references. We hide things by
making their attributes begin with an underscore
_, which makes them
not appear in the docs. For instance, if we create a
Note and look
.duration.client it looks like the Note itself:
from music21 import *
n = note.Note("F##2")
.client is not an attribute or reference at all, but a
property: a small method that is run invisibily without needing
marks that converts a weakref into a normal object. The actual weakref
is stored at
<weakref at 0x107967318; to 'Note' at 0x10798b630>
We have already seen the use of weak references to store clients in the Derivation method:
n.derivation.client is n