<h1><spanclass="section-number">5. </span>Introduction to Python classes and objects<aclass="headerlink"href="#introduction-to-python-classes-and-objects"title="Permalink to this headline">¶</a></h1>
<p>If you followed earlier tutorial lessons, the <codeclass="docutils literal notranslate"><spanclass="pre">mygame/world/test.py</span></code> file should look like this (if
<li><p>Anything on a line after a <codeclass="docutils literal notranslate"><spanclass="pre">#</span></code> is a <codeclass="docutils literal notranslate"><spanclass="pre">comment</span></code>, ignored by Python</p></li>
<p>The <em>python_path</em> describes the relation between Python resources, both between and inside
Python <em>modules</em> (that is, files ending with .py). A python-path separates each part of the
path <codeclass="docutils literal notranslate"><spanclass="pre">.</span></code> and always skips the <codeclass="docutils literal notranslate"><spanclass="pre">.py</span></code> file endings. Also, Evennia already knows to start looking
for python resources inside <codeclass="docutils literal notranslate"><spanclass="pre">mygame/</span></code> so this should never be specified. Hence</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">import</span></code> Python instruction loads <codeclass="docutils literal notranslate"><spanclass="pre">world.test</span></code> so you have it available. You can now go “into”
<p>Using <codeclass="docutils literal notranslate"><spanclass="pre">import</span></code> like this means that you have to specify the full <codeclass="docutils literal notranslate"><spanclass="pre">world.test</span></code> every time you want
to get to your function. Here’s a more powerful form of import:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">...</span><spanclass="pre">import</span><spanclass="pre">...</span></code> is very, very common as long as you want to get something with a longer
python path. It imports <codeclass="docutils literal notranslate"><spanclass="pre">hello_world</span></code> directly, so you can use it right away!</p>
<p>Let’s say your <codeclass="docutils literal notranslate"><spanclass="pre">test.py</span></code> module had a bunch of interesting functions. You could then import them
<p>If there were <em>a lot</em> of functions, you could instead just import <codeclass="docutils literal notranslate"><spanclass="pre">test</span></code> and get the function
from there when you need (without having to give the full <codeclass="docutils literal notranslate"><spanclass="pre">world.test</span></code> every time):</p>
<p>You can also <em>rename</em> stuff you import. Say for example that the module you import to already
has a function <codeclass="docutils literal notranslate"><spanclass="pre">hello_world</span></code> but we also want to use the one from <codeclass="docutils literal notranslate"><spanclass="pre">world/test.py</span></code>:</p>
<p>The form <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">...</span><spanclass="pre">import</span><spanclass="pre">...</span><spanclass="pre">as</span><spanclass="pre">...</span></code> renames the import.</p>
<p>In <aclass="reference internal"href="Beginner-Tutorial-Python-basic-introduction.html"><spanclass="doc std std-doc">the basic intro to Python</span></a> we learned how to open the in-game
<h2><spanclass="section-number">5.2. </span>On classes and objects<aclass="headerlink"href="#on-classes-and-objects"title="Permalink to this headline">¶</a></h2>
<p>A docstring is not the same as a comment (created by <codeclass="docutils literal notranslate"><spanclass="pre">#</span></code>). A docstring is not ignored by Python but is an integral part of the thing it is documenting (the module and the class in this case).</p>
<p>The real file is much longer but we can ignore the multi-line strings (<codeclass="docutils literal notranslate"><spanclass="pre">"""</span><spanclass="pre">...</span><spanclass="pre">"""</span></code>). These serve
as documentation-strings, or <em>docstrings</em> for the module (at the top) and the <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> below.</p>
<p>Below the module doc string we have the import. In this case we are importing a resource
from the core <codeclass="docutils literal notranslate"><spanclass="pre">evennia</span></code> library itself. We will dive into this later, for now we just treat this
as a black box.</p>
<p>Next we have a <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> named <codeclass="docutils literal notranslate"><spanclass="pre">Object</span></code>, which <em>inherits</em> from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>. This class doesn’t
actually do anything on its own, its only code (except the docstring) is <codeclass="docutils literal notranslate"><spanclass="pre">pass</span></code> which means,
<p>We will get back to this module in the <aclass="reference internal"href="Beginner-Tutorial-Learning-Typeclasses.html"><spanclass="doc std std-doc">next lesson</span></a>. First we need to do a
<p>Classes, objects, instances and inheritance are fundamental to Python. This and some other concepts are often clumped together under the term Object-Oriented-Programming (OOP).</p>
<h3><spanclass="section-number">5.2.1. </span>Classes and instances<aclass="headerlink"href="#classes-and-instances"title="Permalink to this headline">¶</a></h3>
<p>A ‘class’ can be seen as a ‘template’ for a ‘type’ of object. The class describes the basic functionality
of everyone of that class. For example, we could have a class <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> which has resources for moving itself
from room to room.</p>
<p>Open a new file <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/monsters.py</span></code>. Add the following simple class:</p>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is moving!"</span><spanclass="p">)</span>
<p>Above we have defined a <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> class with one variable <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> (that is, the name) and one
<em>method</em> on it. A method is like a function except it sits “on” the class. It also always has
at least one argument (almost always written as <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> although you could in principle use
another name), which is a reference back to itself. So when we print <codeclass="docutils literal notranslate"><spanclass="pre">self.key</span></code> we are referring
back to the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> on the class.</p>
<li><p>A <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code> is a code template describing a ‘type’ of something</p></li>
<li><p>An <codeclass="docutils literal notranslate"><spanclass="pre">object</span></code> is an <codeclass="docutils literal notranslate"><spanclass="pre">instance</span></code> of a <codeclass="docutils literal notranslate"><spanclass="pre">class</span></code>. Like using a mold to cast in soldiers, one class can be <codeclass="docutils literal notranslate"><spanclass="pre">instantiated</span></code> into any number of object-instances.</p></li>
<p>A class is just a template. Before it can be used, we must create an <em>instance</em> of the class. If
<codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> is a class, then an instance is Fluffy, the individual red dragon. You instantiate
by <em>calling</em> the class, much like you would a function:</p>
<p>We created an <em>instance</em> of <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code>, which we stored in the variable <codeclass="docutils literal notranslate"><spanclass="pre">fluffy</span></code>. We then
called the <codeclass="docutils literal notranslate"><spanclass="pre">move_around</span></code> method on fluffy to get the printout.</p>
<blockquote>
<div><p>Note how we <em>didn’t</em> call the method as <codeclass="docutils literal notranslate"><spanclass="pre">fluffy.move_around(self)</span></code>. While the <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> has to be
there when defining the method, we <em>never</em> add it explicitly when we call the method (Python
will add the correct <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> for us automatically behind the scenes).</p>
</div></blockquote>
<p>Let’s create the sibling of Fluffy, Cuddly:</p>
<p>We now have two dragons and they’ll hang around until with call <codeclass="docutils literal notranslate"><spanclass="pre">quit()</span></code> to exit this Python
instance. We can have them move as many times as we want. But no matter how many dragons we
create, they will all show the same printout since <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is always fixed as “Monster”.</p>
<p>Let’s make the class a little more flexible:</p>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is moving!"</span><spanclass="p">)</span>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code> is a special method that Python recognizes. If given, this handles extra arguments
when you instantiate a new Monster. We have it add an argument <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> that we store on <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code>.</p>
<p>Now, for Evennia to see this code change, we need to reload the server. You can either do it this
<p>Reloading with the python mode gets a little annoying since you need to redo everything after every reload. Just keep in mind that during regular development you will not be working this way. The in-game python mode is practical for quick fixes and experiments like this, but actual code is normally written externally, in python modules.</p>
<p>Now we passed <codeclass="docutils literal notranslate"><spanclass="pre">"Fluffy"</span></code> as an argument to the class. This went into <codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code> and set <codeclass="docutils literal notranslate"><spanclass="pre">self.key</span></code>, which we
later used to print with the right name! Again, note that we didn’t include <codeclass="docutils literal notranslate"><spanclass="pre">self</span></code> when calling.</p>
<h3><spanclass="section-number">5.2.2. </span>What’s so good about objects?<aclass="headerlink"href="#whats-so-good-about-objects"title="Permalink to this headline">¶</a></h3>
<p>So far all we’ve seen a class do is to behave our first <codeclass="docutils literal notranslate"><spanclass="pre">hello_world</span></code> function but more complex. We
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is moving!"</span><spanclass="p">)</span>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">fluffy</span></code> object’s <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> was changed to “Cuddly” for as long as it’s around. This makes objects
extremely useful for representing and remembering collections of data - some of which can be other
objects in turn:</p>
<ulclass="simple">
<li><p>A player character with all its stats</p></li>
<li><p>A monster with HP</p></li>
<li><p>A chest with a number of gold coins in it</p></li>
<li><p>A room with other objects inside it</p></li>
<li><p>The current policy positions of a political party</p></li>
<li><p>A rule with methods for resolving challenges or roll dice</p></li>
<li><p>A multi-dimenstional data-point for a complex economic simulation</p></li>
<h3><spanclass="section-number">5.2.3. </span>Classes can have children<aclass="headerlink"href="#classes-can-have-children"title="Permalink to this headline">¶</a></h3>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> is moving!"</span><spanclass="p">)</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"</span><spanclass="si">{</span><spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> flies through the air high above!"</span><spanclass="p">)</span>
<p>We added some docstrings for clarity. It’s always a good idea to add doc strings; you can do so also for methods,
as exemplified for the new <codeclass="docutils literal notranslate"><spanclass="pre">firebreath</span></code> method.</p>
<p>We created the new class <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code> but we also specified that <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> is the <em>parent</em> of <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code> but adding
the parent in parenthesis. <codeclass="docutils literal notranslate"><spanclass="pre">class</span><spanclass="pre">Classname(Parent)</span></code> is the way to do this.</p>
<p>It’s possible to add more comma-separated parents to a class. You should usually avoid this until you <codeclass="docutils literal notranslate"><spanclass="pre">really</span></code> know what you are doing. A single parent will be enough for almost every case you’ll need.</p>
<p>Because we didn’t implement <codeclass="docutils literal notranslate"><spanclass="pre">__init__</span></code> in <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code>, we got the one from <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> instead. But since we
implemented our own <codeclass="docutils literal notranslate"><spanclass="pre">move_around</span></code> in <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code>, it <em>overrides</em> the one in <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code>. And <codeclass="docutils literal notranslate"><spanclass="pre">firebreath</span></code> is only
available for <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code>s of course. Having that on <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> would not have made much sense, since not every monster
can breathe fire.</p>
<p>One can also force a class to use resources from the parent even if you are overriding some of it. This is done
with the <codeclass="docutils literal notranslate"><spanclass="pre">super()</span></code> method. Modify your <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code> class as follows:</p>
<div><p>Keep <codeclass="docutils literal notranslate"><spanclass="pre">Monster</span></code> and the <codeclass="docutils literal notranslate"><spanclass="pre">firebreath</span></code> method, <codeclass="docutils literal notranslate"><spanclass="pre">#</span><spanclass="pre">...</span></code> indicates the rest of the code is untouched.</p>
</div></blockquote>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">super().move_around()</span></code> line means that we are calling <codeclass="docutils literal notranslate"><spanclass="pre">move_around()</span></code> on the parent of the class. So in this
case, we will call <codeclass="docutils literal notranslate"><spanclass="pre">Monster.move_around</span></code> first, before doing our own thing.</p>
<p>Now <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code> the server and then:</p>
<p>We can see that <codeclass="docutils literal notranslate"><spanclass="pre">Monster.move_around()</span></code> is calls first and prints “Smaug is moving!”, followed by the extra bit
about the trembling world we added in the <codeclass="docutils literal notranslate"><spanclass="pre">Dragon</span></code> class.</p>
<p>Inheritance is very powerful because it allows you to organize and re-use code while only adding the special things
you want to change. Evennia uses this concept a lot.</p>