Tutorial: Objects and Classes in Python and Sage -- Thematic Tutorials v4.7.rc0
system:sage


<div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index" accesskey="I">index</a></li>
  
    
      <a href="../index.html"><img src="_static/sagelogo.png" style="vertical-align: middle" title="Sage Logo"></a>
    
  
  
        <li><a href="index.html">Thematic Tutorials v4.7.rc0</a> &raquo;</li>
 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="tutorial-objects-and-classes-in-python-and-sage">
<span id="tutorial-objects-and-classes"></span><h1>Tutorial: Objects and Classes in Python and Sage<a class="headerlink" href="#tutorial-objects-and-classes-in-python-and-sage" title="Permalink to this headline">¶</a></h1>
<p><em>Author: Florent Hivert &lt;<a class="reference external" href="mailto:florent.hivert%40univ-rouen.fr">florent<span>&#46;</span>hivert<span>&#64;</span>univ-rouen<span>&#46;</span>fr</a>&gt;</em></p>
<p>This tutorial is an introduction to object oriented programming in Python and
Sage. It requires basic knowledges on imperative/procedural programming (the
most common programming style) that is conditional instructions, loops,
functions (see <a class="reference internal" href="tutorial-programming-python.html#tutorial-programming-python"><em>Tutorial: Programming in Python and Sage</em></a>), but now further knowledge
about objects and classes is assumed. It is designed as an alternating
sequence of formal introduction and exercises. <a class="reference internal" href="#solutions"><em>Solutions to the exercises</em></a> are given at
the end.</p>
<div class="section" id="foreword-variables-names-and-objects">
<h2>Foreword: variables, names and objects<a class="headerlink" href="#foreword-variables-names-and-objects" title="Permalink to this headline">¶</a></h2>
<p>As an object oriented, language, Python&#8217;s &#8216;&#8217;variables&#8217;&#8217; behavior may be
surprising for people used to imperative language like C or Maple. The reason
is because they are <strong>not variables but names</strong>.</p>
<p>The following explanation is borrowed from
<a class="reference external" href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#python-has-names">David Goodger</a>.</p>
</div>
<div class="section" id="other-languages-have-variables">
<h2>Other languages have &#8220;variables&#8221;<a class="headerlink" href="#other-languages-have-variables" title="Permalink to this headline">¶</a></h2>
<div class="handout container">
In many other languages, assigning to a variable puts a value into
a box.</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="50%">
<col width="50%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><pre>int a = 1;</pre>
</div>
</td>
<td><img alt="_images/a1box.png" class="incremental first last" src="_images/a1box.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
<p>Box &#8220;a&#8221; now contains an integer 1.</p>
<p>Assigning another value to the same variable replaces the contents
of the box:</p>
</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="50%">
<col width="50%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><div class="highlight"><pre>a = 2;
</pre></div></div>
</td>
<td><img alt="_images/a2box.png" class="incremental first last" src="_images/a2box.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
<p>Now box &#8220;a&#8221; contains an integer 2.</p>
<p>Assigning one variable to another makes a copy of the value and
puts it in the new box:</p>
</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="33%">
<col width="33%">
<col width="33%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><pre>int b = a;</pre>
</div>
</td>
<td><img alt="_images/b2box.png" class="incremental first last" src="_images/b2box.png">
</td>
<td><img alt="_images/a2box.png" class="incremental first last" src="_images/a2box.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
&#8220;b&#8221; is a second box, with a copy of integer 2.  Box &#8220;a&#8221; has a
separate copy.</div>
</div>
<div class="section" id="python-has-names">
<h2>Python has &#8220;names&#8221;<a class="headerlink" href="#python-has-names" title="Permalink to this headline">¶</a></h2>
<div class="handout container">
In Python, a &#8220;name&#8221; or &#8220;identifier&#8221; is like a parcel tag (or
nametag) attached to an object.</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="50%">
<col width="50%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><div class="highlight"><pre>a = 1
</pre></div></div>
</td>
<td><img alt="_images/a1tag.png" class="incremental first last" src="_images/a1tag.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
<p>Here, an integer 1 object has a tag labelled &#8220;a&#8221;.</p>
<p>If we reassign to &#8220;a&#8221;, we just move the tag to another object:</p>
</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="33%">
<col width="33%">
<col width="33%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><div class="highlight"><pre>a = 2
</pre></div></div>
</td>
<td><img alt="_images/a2tag.png" class="incremental first last" src="_images/a2tag.png">
</td>
<td><img alt="_images/1.png" class="incremental first last" src="_images/1.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
<p>Now the name &#8220;a&#8221; is attached to an integer 2 object.</p>
<p>The original integer 1 object no longer has a tag &#8220;a&#8221;.  It may live
on, but we can&#8217;t get to it through the name &#8220;a&#8221;.  (When an object
has no more references or tags, it is removed from memory.)</p>
<p>If we assign one name to another, we&#8217;re just attaching another
nametag to an existing object:</p>
</div>
<table border="1" class="incremental borderless docutils">
<colgroup>
<col width="50%">
<col width="50%">
</colgroup>
<tbody valign="top">
<tr><td><div class="first last highlight-python"><div class="highlight"><pre>b = a
</pre></div></div>
</td>
<td><img alt="_images/ab2tag.png" class="incremental first last" src="_images/ab2tag.png">
</td>
</tr>
</tbody>
</table>
<div class="handout container">
<p>The name &#8220;b&#8221; is just a second tag bound to the same object as &#8220;a&#8221;.</p>
<p>Although we commonly refer to &#8220;variables&#8221; even in Python (because
it&#8217;s common terminology), we really mean &#8220;names&#8221; or &#8220;identifiers&#8221;.
In Python, &#8220;variables&#8221; are nametags for values, not labelled boxes.</p>
</div>
<p>As a consequence:</p>
<div class="highlight-python">

{{{id=0|
l = [1,2,3]
l1 = l
l1[1] = 0
l
///
[1, 0, 3]
}}}

</div>
</div>
<div class="section" id="object-oriented-programming-paradigm">
<h2>Object oriented programming paradigm<a class="headerlink" href="#object-oriented-programming-paradigm" title="Permalink to this headline">¶</a></h2>
<p>The object oriented programming paradigm relies on the two following
fundamental rules:</p>
<ol class="arabic simple">
<li>Any thing of the real (or mathematical) world which needs to be manipulated
by the computer is modeled by an <strong>object</strong>.</li>
<li>Each object is an <strong>instance</strong> of some <strong>class</strong>.</li>
</ol>
<p>At this point, those two rules are a little meaningless, so let&#8217;s give some
more or less precise definition of the terms:</p>
<hr class="docutils">
<dl class="docutils">
<dt><strong>object</strong></dt>
<dd>a <strong>portion of memory</strong> which contains the information needed to model
the real world thing.</dd>
<dt><strong>class</strong></dt>
<dd>defines the <strong>data structure</strong> used to store the objects which are instance
of the class together with their <strong>behavior</strong>.</dd>
</dl>
<hr class="docutils">
<p>Let&#8217;s start with some examples: We consider the vector space over <img class="math" src="_images/math/156c0e43da2df99cae1c91cfcff9bfa48e8709c1.png" alt="\QQ"> whose
basis is indexed by permutations, and a particular element in it:</p>
<div class="highlight-python">

{{{id=1|
F = CombinatorialFreeModule(QQ, Permutations())
el = 3*F([1,3,2])+ F([1,2,3])
el
///
B[[1, 2, 3]] + 3*B[[1, 3, 2]]
}}}

</div>
<p>In python, everything is an object so there isn&#8217;t any difference between types
and classes. On can get the class of the object <tt class="docutils literal"><span class="pre">el</span></tt> by:</p>
<div class="highlight-python">

{{{id=2|
type(el)
///
<class 'sage.combinat.free_module.CombinatorialFreeModule_with_category.element_class'>
}}}

</div>
<p>As such, this is not very informative. We&#8217;ll go back to it later. The data
associated to objects are stored in so called <strong>attributes</strong>. They are
accessed through the syntax <tt class="docutils literal"><span class="pre">obj.attributes_name</span></tt>:</p>
<div class="highlight-python">

{{{id=3|
el._monomial_coefficients
///
{[1, 2, 3]: 1, [1, 3, 2]: 3}
}}}

</div>
<p>Modifying the attribute modifies the objects:</p>
<div class="highlight-python">

{{{id=4|
el._monomial_coefficients[Permutation([3,2,1])] = 1/2
el
///
B[[1, 2, 3]] + 3*B[[1, 3, 2]] + 1/2*B[[3, 2, 1]]
}}}

</div>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">as a user, you are <em>not</em> supposed to do that by yourself (see
note on <a class="reference internal" href="#private-attributes"><em>private attributes</em></a> below).</p>
</div>
<p>As an element of a vector space <tt class="docutils literal"><span class="pre">el</span></tt> has a particular behavior:</p>
<div class="highlight-python">

{{{id=5|
2*el
///
2*B[[1, 2, 3]] + 6*B[[1, 3, 2]] + B[[3, 2, 1]]
}}}

{{{id=6|
el.support()
///
[[1, 2, 3], [1, 3, 2], [3, 2, 1]]
}}}

{{{id=7|
el.coefficient([1, 2, 3])
///
1
}}}

</div>
<p>The behavior is defined through <strong>methods</strong> (<tt class="docutils literal"><span class="pre">support,</span> <span class="pre">coefficient</span></tt>). Note
that this is true, even for equality, printing or mathematical operations. For
example the call <tt class="docutils literal"><span class="pre">a</span> <span class="pre">==</span> <span class="pre">b</span></tt> actually is translated to the method call
<tt class="docutils literal"><span class="pre">a.__eq__(b)</span></tt>. The names of those special methods which are usually called
through operators are fixed by the Python language and are of the form
<tt class="docutils literal"><span class="pre">__name__</span></tt>. Example include <tt class="docutils literal"><span class="pre">__eq__</span></tt>, <tt class="docutils literal"><span class="pre">__le__</span></tt> for operators <tt class="docutils literal"><span class="pre">==</span></tt> and
<tt class="docutils literal"><span class="pre">&lt;=</span></tt>, <tt class="docutils literal"><span class="pre">__repr__</span></tt> (see <a class="reference internal" href="#sage-specifics"><em>Sage specifics about classes</em></a>) for printing, <tt class="docutils literal"><span class="pre">__add__</span></tt> and
<tt class="docutils literal"><span class="pre">__mult__</span></tt> for operators <tt class="docutils literal"><span class="pre">+</span></tt> and <tt class="docutils literal"><span class="pre">*</span></tt> (see
<a class="reference external" href="http://docs.python.org/library/">http://docs.python.org/library/</a>) for a complete list:</p>
<div class="highlight-python">

{{{id=8|
el.__eq__(F([1,3,2]))
///
False
}}}

{{{id=9|
el.__repr__()
///
'B[[1, 2, 3]] + 3*B[[1, 3, 2]] + 1/2*B[[3, 2, 1]]'
}}}

{{{id=10|
el.__mul__(2)
///
2*B[[1, 2, 3]] + 6*B[[1, 3, 2]] + B[[3, 2, 1]]
}}}

</div>
<p>Some particular actions allows to modify the data structure of <tt class="docutils literal"><span class="pre">el</span></tt>:</p>
<div class="highlight-python">

{{{id=11|
el.rename(&quot;bla&quot;)
el
///
bla
}}}

</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>The class is stored in a particular attribute called <tt class="docutils literal"><span class="pre">__class__</span></tt> the
normal attribute are stored in a dictionary called <tt class="docutils literal"><span class="pre">__dict__</span></tt>:</p>
<div class="highlight-python">

{{{id=12|
F = CombinatorialFreeModule(QQ, Permutations())
el = 3*F([1,3,2])+ F([1,2,3])
el.rename(&quot;foo&quot;)
el.__class__
///
 <class 'sage.combinat.free_module.CombinatorialFreeModule_with_category.element_class'>
}}}

{{{id=13|
el.__dict__
///
{'_monomial_coefficients': {[1, 2, 3]: 1, [1, 3, 2]: 3}, '__custom_name': 'foo'}
}}}

</div>
<p>Lots of sage objects are not Python objects but compiled Cython
objects. Python sees them as builtin objects and you don&#8217;t have access to
the data structure. Examples include integers and permutation group
elements:</p>
<div class="last highlight-python">

{{{id=14|
e = Integer(9)
type(e)
///
<type 'sage.rings.integer.Integer'>
}}}

{{{id=15|
e.__dict__
///
<dictproxy object at 0x...>
}}}

{{{id=16|
e.__dict__.keys()
///
['__module__', '_reduction', '__doc__', '_sage_src_lines_']
}}}

{{{id=17|
id4 = SymmetricGroup(4).one()
type(id4)
///
<type 'sage.groups.perm_gps.permgroup_element.PermutationGroupElement'>
}}}

{{{id=18|
id4.__dict__
///
<dictproxy object at 0x...>
}}}

</div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>Each objects corresponds to a portion of memory called its <strong>identity</strong> in
python. You can get the identity using <tt class="docutils literal"><span class="pre">id</span></tt>:</p>
<div class="highlight-python">

{{{id=19|
el = Integer(9)
id(el)  # random
///
139813642977744
}}}

{{{id=20|
el1 = el; id(el1) == id(el)
///
True
}}}

{{{id=21|
el1 is el
///
True
}}}

</div>
<p>This is different from mathematical identity:</p>
<div class="last highlight-python">

{{{id=22|
el2 = Integer(9)
el2 == el1
///
True
}}}

{{{id=23|
el2 is el1
///
False
}}}

{{{id=24|
id(el2) == id(el)
///
False
}}}

</div>
</div>
<div class="section" id="summary">
<h3>Summary<a class="headerlink" href="#summary" title="Permalink to this headline">¶</a></h3>
<p>To define some object, you first have to write a <strong>class</strong>. The class will
defines the methods and the attributes of the object.</p>
<dl class="docutils">
<dt><strong>method</strong></dt>
<dd>particular kind of function associated with an object used to get
information about the object or to manipulate it.</dd>
<dt><strong>attribute</strong></dt>
<dd>variables where the info about the object are stored;</dd>
</dl>
</div>
<div class="section" id="an-example-glass-of-beverage-in-a-restaurant">
<h3>An example: glass of beverage in a restaurant<a class="headerlink" href="#an-example-glass-of-beverage-in-a-restaurant" title="Permalink to this headline">¶</a></h3>
<p>Let&#8217;s write a small class about glasses in a restaurant:</p>
<div class="highlight-python">

{{{id=25|
class Glass(object):
       def __init__(self, size):
           assert size &gt; 0
           self._size = float(size)
           self._content = float(0.0)
       def __repr__(self):
           if self._content == 0.0:
               return &quot;An empty glass of size %s&quot;%(self._size)
           else:
               return &quot;A glass of size %s cl containing %s cl of water&quot;%(
                       self._size, self._content)
       def fill(self):
           self._content = self._size
       def empty(self):
           self._content = float(0.0)
///
}}}

</div>
<p>Let&#8217;s create a small glass:</p>
<div class="highlight-python">

{{{id=26|
myGlass = Glass(10); myGlass
///
An empty glass of size 10.0
}}}

{{{id=27|
myGlass.fill(); myGlass
///
A glass of size 10.0 cl containing 10.0 cl of water
}}}

{{{id=28|
myGlass.empty(); myGlass
///
An empty glass of size 10.0
}}}

</div>
<p>Some comments:</p>
<ol class="arabic simple">
<li>The method <tt class="docutils literal"><span class="pre">__init__</span></tt> is used to initialize the object, it is used by the
so called <strong>constructor</strong> of the class that is executed when calling
<tt class="docutils literal"><span class="pre">Glass(10)</span></tt>.</li>
<li>The method <tt class="docutils literal"><span class="pre">__repr__</span></tt> is supposed to return a string which is used to
print the object.</li>
</ol>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p><strong>Private Attributes</strong></p>
<ul class="last simple" id="private-attributes">
<li>most of the time, in order to ensure consistency of the data structures,
the user should not be allowed to change directly the attribute of an
object. Those attributes are called <strong>private</strong>. Since there is no
mechanism to ensure privacy in python, the convention is the following:
private attribute are marked by an underscore.</li>
<li>as a consequence attribute access is only made through methods. Methods
for reading or writing a private attribute are called accessors.</li>
<li>methods which are only for internal use are also prefixed with an
underscore.</li>
</ul>
</div>
</div>
<div class="section" id="exercises">
<h3>Exercises<a class="headerlink" href="#exercises" title="Permalink to this headline">¶</a></h3>
<ol class="arabic simple">
<li>add a method <tt class="docutils literal"><span class="pre">is_empty</span></tt> which returns true if a glass is empty.</li>
<li>define a method <tt class="docutils literal"><span class="pre">drink</span></tt> with a parameter <tt class="docutils literal"><span class="pre">amount</span></tt> which allows to
partially drink the water in the glass. Raise an error if one asks to
drink more water than there is in the glass or a negative amount of
water.</li>
<li>Allows the glass to be filled with wine, beer or other beverage. The method
<tt class="docutils literal"><span class="pre">fill</span></tt> should accept a parameter <tt class="docutils literal"><span class="pre">beverage</span></tt>. The beverage is stored in
an attribute <tt class="docutils literal"><span class="pre">_beverage</span></tt>. Update the method <tt class="docutils literal"><span class="pre">__repr__</span></tt> accordingly.</li>
<li>Add an attribute <tt class="docutils literal"><span class="pre">_clean</span></tt> and methods <tt class="docutils literal"><span class="pre">is_clean</span></tt> and <tt class="docutils literal"><span class="pre">wash</span></tt>. At the
creation a glass is clean, as soon as it&#8217;s filled it becomes dirty, and must
be washed to become clean again.</li>
<li>Test everything.</li>
<li>Make sure that everything is tested.</li>
<li>Test everything again.</li>
</ol>
</div>
</div>
<div class="section" id="inheritance">
<h2>Inheritance<a class="headerlink" href="#inheritance" title="Permalink to this headline">¶</a></h2>
<p>The problem: object of <strong>different</strong> classes may share a <strong>common behavior</strong>.</p>
<p>For example, if one wants to deal now with different dishes (forks, spoons
...) then there is common behavior (becoming dirty and being washed). So the
different classes associated to the different kinds of dishes should have the
same <tt class="docutils literal"><span class="pre">clean</span></tt>, <tt class="docutils literal"><span class="pre">is_clean</span></tt> and <tt class="docutils literal"><span class="pre">wash</span></tt> methods. But copying and pasting
code is very bad for maintenance: mistake are copied, and to change anything
one has to remember the location of all the copy ! So there is a need for a
mechanism which allows to factorizes the common behavior. It is called
<strong>inheritance</strong> or <strong>sub-classing</strong>: one write a base class which factorizes
the common behavior and reuse the methods from this class.</p>
<p>We first write a small class &#8216;&#8217;AbstractDish&#8217;&#8217; which implement the
&#8220;clean-dirty-wash&#8221; behavior:</p>
<div class="highlight-python">

{{{id=29|
class AbstractDish(object):
       def __init__(self):
           self._clean = True
       def is_clean(self):
           return self._clean
       def state(self):
           return &quot;clean&quot; if self.is_clean() else &quot;dirty&quot;
       def __repr__(self):
           return &quot;An unspecified %s dish&quot;%self.state()
       def _make_dirty(self):
           self._clean = False
       def wash(self):
           self._clean = True
///
}}}

</div>
<p>Now one can reuse this behavior within a class <tt class="docutils literal"><span class="pre">Spoon</span></tt>:</p>
<div class="highlight-python">

{{{id=30|
class Spoon(AbstractDish):
       def __repr__(self):
           return &quot;A %s spoon&quot;%self.state()
       def eat_with(self):
           self._make_dirty()
///
}}}

</div>
<p>Let&#8217;s tests it:</p>
<div class="highlight-python">

{{{id=31|
s = Spoon(); s
///
A clean spoon
}}}

{{{id=32|
s.is_clean()
///
True
}}}

{{{id=33|
s.eat_with(); s
///
A dirty spoon
}}}

{{{id=34|
s.is_clean()
///
False
}}}

{{{id=35|
s.wash(); s
///
A clean spoon
}}}

</div>
<div class="section" id="id1">
<h3>Summary<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
<ol class="arabic">
<li><p class="first">Any class can reuse the behavior of another class. One says that the
subclass <strong>inherits</strong> from the superclass or that it <strong>derives</strong> from it.</p>
</li>
<li><p class="first">Any instance of the subclass is also an instance its superclass:</p>
<div class="highlight-python">

{{{id=36|
type(s)
///
<class '__main__.Spoon'>
}}}

{{{id=37|
isinstance(s, Spoon)
///
True
}}}

{{{id=38|
isinstance(s, AbstractDish)
///
True
}}}

</div>
</li>
<li><p class="first">If a subclass redefines a method, then it replaces the former one. One says
that the subclass <strong>overloads</strong> the method. One can nevertheless explicitly
call the hidden superclass method.</p>
<div class="highlight-python">

{{{id=39|
s.__repr__()
///
'A clean spoon'
}}}

{{{id=40|
Spoon.__repr__(s)
///
'A clean spoon'
}}}

{{{id=41|
AbstractDish.__repr__(s)
///
'An unspecified clean dish'
}}}

</div>
</li>
</ol>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p><strong>Advanced superclass method call</strong></p>
<p>Sometimes one wants to call an overloaded method without knowing in which
class it is defined. On use the <tt class="docutils literal"><span class="pre">super</span></tt> operator:</p>
<div class="highlight-python">

{{{id=42|
super(Spoon, s).__repr__()
///
'An unspecified clean dish'
}}}

</div>
<p>A very common usage of this construct is to call the __init__ method of the
super classes:</p>
<div class="last highlight-python">

{{{id=43|
class Spoon(AbstractDish):
       def __init__(self):
           print &quot;Building a spoon&quot;
           super(Spoon, self).__init__()
       def __repr__(self):
           return &quot;A %s spoon&quot;%self.state()
       def eat_with(self):
           self.make_dirty()
s = Spoon()
///
Building a spoon
}}}

{{{id=44|
s
///
A clean spoon
}}}

</div>
</div>
</div>
<div class="section" id="id2">
<h3>Exercises<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h3>
<ol class="arabic simple">
<li>Modify the class <tt class="docutils literal"><span class="pre">Glasses</span></tt> so that it inherits from <tt class="docutils literal"><span class="pre">Dish</span></tt>.</li>
<li>Write a class <tt class="docutils literal"><span class="pre">Plate</span></tt> whose instance can contain any meals together with
a class <tt class="docutils literal"><span class="pre">Fork</span></tt>. Avoid at much as possible code duplication (hint:
you can write a factorized class <tt class="docutils literal"><span class="pre">ContainerDish</span></tt>).</li>
<li>Test everything.</li>
</ol>
</div>
</div>
<div class="section" id="sage-specifics-about-classes">
<span id="sage-specifics"></span><h2>Sage specifics about classes<a class="headerlink" href="#sage-specifics-about-classes" title="Permalink to this headline">¶</a></h2>
<p>Compared to Python, Sage has its particular way to handles objects:</p>
<ul class="simple">
<li>Any classes for mathematical objects in Sage should inherits from
<tt class="docutils literal"><span class="pre">SageObject</span></tt> rather than from <tt class="docutils literal"><span class="pre">object</span></tt>.</li>
<li>Printing should be done through <tt class="docutils literal"><span class="pre">_repr_</span></tt> instead of <tt class="docutils literal"><span class="pre">__repr__</span></tt> to allows
for renaming.</li>
<li>More generally, Sage specific special methods are usually named <tt class="docutils literal"><span class="pre">_meth_</span></tt>
rather than <tt class="docutils literal"><span class="pre">__meth__</span></tt>. For example, lots of classes implement <tt class="docutils literal"><span class="pre">_hash_</span></tt>
which is used and cached by <tt class="docutils literal"><span class="pre">__hash__</span></tt>.</li>
</ul>
</div>
<div class="section" id="solutions-to-the-exercises">
<span id="solutions"></span><h2>Solutions to the exercises<a class="headerlink" href="#solutions-to-the-exercises" title="Permalink to this headline">¶</a></h2>
<ol class="arabic">
<li><p class="first">Here is a solution to the first exercise:</p>
<div class="highlight-python">

{{{id=45|
class Glass(object):
       def __init__(self, size):
           assert size &gt; 0
           self._size = float(size)
           self.wash()
       def __repr__(self):
           if self._content == 0.0:
               return &quot;An empty glass of size %s&quot;%(self._size)
           else:
               return &quot;A glass of size %s cl containing %s cl of %s&quot;%(
                       self._size, self._content, self._beverage)
       def content(self):
           return self._content
       def beverage(self):
           return self._beverage
       def fill(self, beverage = &quot;water&quot;):
           if not self.is_clean():
               raise ValueError, &quot;Don&#39;t want to fill a dirty glass&quot;
           self._clean = False
           self._content = self._size
           self._beverage = beverage
       def empty(self):
           self._content = float(0.0)
       def is_empty(self):
           return self._content == 0.0
       def drink(self, amount):
           if amount &lt;= 0.0:
               raise ValueError, &quot;amount must be positive&quot;
           elif amount &gt; self._content:
               raise ValueError, &quot;not enough beverage in the glass&quot;
           else:
               self._content -= float(amount)
       def is_clean(self):
           return self._clean
       def wash(self):
           self._content = float(0.0)
           self._beverage = None
           self._clean = True
///
}}}

</div>
</li>
<li><p class="first">Let&#8217;s check that everything is working as expected:</p>
<div class="highlight-python">

{{{id=46|
G = Glass(10.0)
G
///
An empty glass of size 10.0
}}}

{{{id=47|
G.is_empty()
///
True
}}}

{{{id=48|
G.drink(2)
///
Traceback (most recent call last):

ValueError: not enough beverage in the glass
}}}

{{{id=49|
G.fill(&quot;beer&quot;)
G
///
A glass of size 10.0 cl containing 10.0 cl of beer
}}}

{{{id=50|
G.is_empty()
///
False
}}}

{{{id=51|
G.is_clean()
///
False
}}}

{{{id=52|
G.drink(5.0)
G
///
A glass of size 10.0 cl containing 5.0 cl of beer
}}}

{{{id=53|
G.is_empty()
///
False
}}}

{{{id=54|
G.is_clean()
///
False
}}}

{{{id=55|
G.drink(5)
G
///
An empty glass of size 10.0
}}}

{{{id=56|
G.is_clean()
///
False
}}}

{{{id=57|
G.fill(&quot;orange juice&quot;)
///
Traceback (most recent call last):

ValueError: Don't want to fill a dirty glass
}}}

{{{id=58|
G.wash()
G
///
An empty glass of size 10.0
}}}

{{{id=59|
G.fill(&quot;orange juice&quot;)
G
///
A glass of size 10.0 cl containing 10.0 cl of orange juice
}}}

</div>
</li>
</ol>
<p>Here is the solution to the second exercice:</p>
<div class="highlight-python">

{{{id=60|
class ContainerDish(AbstractDish):
       def __init__(self, size):
           assert size &gt; 0
           self._size = float(size)
           super(Glass, self).__init__()
       def content(self):
           return self._content
       def empty(self):
           self._content = float(0.0)
       def is_empty(self):
           return self._content == 0.0
///
}}}

{{{id=61|
class Glass(ContainerDish):
       def __repr__(self):
           if self._content == 0.0:
               return &quot;An empty glass of size %s&quot;%(self._size)
           else:
               return &quot;A glass of size %s cl containing %s cl of %s&quot;%(
                       self._size, self._content, self._beverage)
       def beverage(self):
           return self._beverage
       def fill(self, beverage = &quot;water&quot;):
           if not self.is_clean():
               raise ValueError, &quot;Don&#39;t want to fill a dirty glass&quot;
           self.make_dirty()
           self._content = self._size
           self._beverage = beverage
       def drink(self, amount):
           if amount &lt;= 0.0:
               raise ValueError, &quot;amount must be positive&quot;
           elif amount &gt; self._content:
               raise ValueError, &quot;not enough beverage in the glass&quot;
           else:
               self._content -= float(amount)
       def wash(self):
           self._content = float(0.0)
           self._beverage = None
           super(Glass, self).__wash__(self)
///
}}}

</div>
<ol class="arabic simple">
<li>Let&#8217;s check that everything is working as expected:</li>
</ol>
<blockquote>
<div class="admonition-todo admonition " id="index-0">
<p class="first admonition-title">Todo</p>
<p class="last">Write demo and tests</p>
</div>
</blockquote>
<p>That all folks !</p>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
            <h3><a href="index.html">Table Of Contents</a></h3>
            <ul>
<li><a class="reference internal" href="#">Tutorial: Objects and Classes in Python and Sage</a><ul>
<li><a class="reference internal" href="#foreword-variables-names-and-objects">Foreword: variables, names and objects</a></li>
<li><a class="reference internal" href="#other-languages-have-variables">Other languages have &#8220;variables&#8221;</a></li>
<li><a class="reference internal" href="#python-has-names">Python has &#8220;names&#8221;</a></li>
<li><a class="reference internal" href="#object-oriented-programming-paradigm">Object oriented programming paradigm</a><ul>
<li><a class="reference internal" href="#summary">Summary</a></li>
<li><a class="reference internal" href="#an-example-glass-of-beverage-in-a-restaurant">An example: glass of beverage in a restaurant</a></li>
<li><a class="reference internal" href="#exercises">Exercises</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inheritance">Inheritance</a><ul>
<li><a class="reference internal" href="#id1">Summary</a></li>
<li><a class="reference internal" href="#id2">Exercises</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sage-specifics-about-classes">Sage specifics about classes</a></li>
<li><a class="reference internal" href="#solutions-to-the-exercises">Solutions to the exercises</a></li>
</ul>
</li>
</ul>

            <h3>This Page</h3>
            <ul class="this-page-menu">
              <li><a href="_sources/tutorial-objects-and-classes.txt" rel="nofollow">Show Source</a></li>
            </ul>
          <div id="searchbox" style="display: none">
            <h3>Quick search</h3>
              <p class="searchtip" style="font-size: 90%">
              Enter search terms or a module, class or function name.
              </p>
          </div>
          <script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index">index</a></li>
  
    
      <a href="../index.html"><img src="_static/sagelogo.png" style="vertical-align: middle" title="Sage Logo"></a>
    
  
  
        <li><a href="index.html">Thematic Tutorials v4.7.rc0</a> &raquo;</li>
 
      </ul>
    </div>
    
    <div class="footer">
        &copy; Copyright 2005--2011, The Sage Development Team.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.0.4.
    </div>
    <script type="text/javascript">
/*global jQuery, window */
/* Sphinx sidebar toggle.  Putting this code at the end of the body
 * enables the toggle for the live, static, and offline docs.  Note:
 * sage.misc.html.math_parse() eats jQuery's dollar-sign shortcut. */
var jq = jQuery;  
jq(document).ready(function () {
    var bar, bod, bg, fg, key, tog, wid_old, wid_new, resize, get_state, set_state;
    bod = jq('div.bodywrapper');
    bar = jq('div.sphinxsidebar');
    tog = jq('<div class="sphinxsidebartoggle"></div>');
    
    /* Delayed resize helper.  Not perfect but good enough. */
    resize = function () {
        setTimeout(function () {
            tog.height(bod.height());
        }, 100);
    };
    jq(window).resize(function () {
        resize();
    });
    
    /* Setup and add the toggle. See Sphinx v0.5.1 default.css. */
    fg = jq('div.sphinxsidebar p a').css('color') || 'rgb(152, 219, 204)';
    bg = jq('div.document').css('background-color') || 'rgb(28, 78, 99)';
    wid_old = '230px';
    wid_new = '5px';
    tog.css('background-color', bg)
        .css('border-width', '0px')
        .css('border-right', wid_new + ' ridge ' + bg)
        .css('cursor', 'pointer')
        .css('position', 'absolute')
        .css('left', '-' + wid_new)
        .css('top', '0px')
        .css('width', wid_new);
    bod.css('position', 'relative');
    bod.prepend(tog);
    resize();
    
    /* Cookie helpers. */
    key = 'sphinxsidebar=';
    set_state = function (s) {
        var date = new Date();
        /* Expiry in 7 days. */
        date.setTime(date.getTime() + (7 * 24 * 3600 * 1000));
        document.cookie = key + encodeURIComponent(s) + '; expires=' +
            date.toUTCString() + '; path=/';
    };
    get_state = function () {
        var i, c, crumbs = document.cookie.split(';');
        for (i = 0; i < crumbs.length; i += 1) {
            c = crumbs[i].replace(/^\s+/, '');
            if (c.indexOf(key) === 0) {
                return decodeURIComponent(c.substring(key.length, c.length));
            }
        }
        return null;
    };
    
    /* Event handlers. */
    tog.mouseover(function (ev) {
        tog.css('border-right-color', fg);
    }).mouseout(function (ev) {
        tog.css('border-right-color', bg);
    }).click(function (ev) {
        if (bod.hasClass('wide')) {
            bod.removeClass('wide');
            bod.css('margin-left', wid_old);
            bar.css('width', wid_old);
            bar.show();
            set_state('visible');
        } else {
            set_state('hidden');
            bar.hide();
            bar.css('width', '0px');
            bod.css('margin-left', wid_new);
            bod.addClass('wide');
        }
        resize();
    });
    
    /* Hide the normally visible sidebar? */
    if (get_state() === 'hidden') {
        tog.trigger('click');
    } else {
        set_state('visible');
    }
});
    </script>