999 lines
91 KiB
HTML
999 lines
91 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8" />
|
|||
|
<title>9. Classes — Python 3.7.4 documentation</title>
|
|||
|
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|||
|
|
|||
|
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/doctools.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/language_data.js"></script>
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/sidebar.js"></script>
|
|||
|
|
|||
|
<link rel="search" type="application/opensearchdescription+xml"
|
|||
|
title="Search within Python 3.7.4 documentation"
|
|||
|
href="../_static/opensearch.xml"/>
|
|||
|
<link rel="author" title="About these documents" href="../about.html" />
|
|||
|
<link rel="index" title="Index" href="../genindex.html" />
|
|||
|
<link rel="search" title="Search" href="../search.html" />
|
|||
|
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
|||
|
<link rel="next" title="10. Brief Tour of the Standard Library" href="stdlib.html" />
|
|||
|
<link rel="prev" title="8. Errors and Exceptions" href="errors.html" />
|
|||
|
<link rel="shortcut icon" type="image/png" href="../_static/py.png" />
|
|||
|
<link rel="canonical" href="https://docs.python.org/3/tutorial/classes.html" />
|
|||
|
|
|||
|
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
|||
|
<script type="text/javascript" src="../_static/switchers.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<style>
|
|||
|
@media only screen {
|
|||
|
table.full-width-table {
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|
|||
|
|
|||
|
|
|||
|
</head><body>
|
|||
|
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<h3>Navigation</h3>
|
|||
|
<ul>
|
|||
|
<li class="right" style="margin-right: 10px">
|
|||
|
<a href="../genindex.html" title="General Index"
|
|||
|
accesskey="I">index</a></li>
|
|||
|
<li class="right" >
|
|||
|
<a href="../py-modindex.html" title="Python Module Index"
|
|||
|
>modules</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="stdlib.html" title="10. Brief Tour of the Standard Library"
|
|||
|
accesskey="N">next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="errors.html" title="8. Errors and Exceptions"
|
|||
|
accesskey="P">previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">The Python Tutorial</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<div class="document">
|
|||
|
<div class="documentwrapper">
|
|||
|
<div class="bodywrapper">
|
|||
|
<div class="body" role="main">
|
|||
|
|
|||
|
<div class="section" id="classes">
|
|||
|
<span id="tut-classes"></span><h1>9. Classes<a class="headerlink" href="#classes" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p>Classes provide a means of bundling data and functionality together. Creating
|
|||
|
a new class creates a new <em>type</em> of object, allowing new <em>instances</em> of that
|
|||
|
type to be made. Each class instance can have attributes attached to it for
|
|||
|
maintaining its state. Class instances can also have methods (defined by its
|
|||
|
class) for modifying its state.</p>
|
|||
|
<p>Compared with other programming languages, Python’s class mechanism adds classes
|
|||
|
with a minimum of new syntax and semantics. It is a mixture of the class
|
|||
|
mechanisms found in C++ and Modula-3. Python classes provide all the standard
|
|||
|
features of Object Oriented Programming: the class inheritance mechanism allows
|
|||
|
multiple base classes, a derived class can override any methods of its base
|
|||
|
class or classes, and a method can call the method of a base class with the same
|
|||
|
name. Objects can contain arbitrary amounts and kinds of data. As is true for
|
|||
|
modules, classes partake of the dynamic nature of Python: they are created at
|
|||
|
runtime, and can be modified further after creation.</p>
|
|||
|
<p>In C++ terminology, normally class members (including the data members) are
|
|||
|
<em>public</em> (except see below <a class="reference internal" href="#tut-private"><span class="std std-ref">Private Variables</span></a>), and all member functions are
|
|||
|
<em>virtual</em>. As in Modula-3, there are no shorthands for referencing the object’s
|
|||
|
members from its methods: the method function is declared with an explicit first
|
|||
|
argument representing the object, which is provided implicitly by the call. As
|
|||
|
in Smalltalk, classes themselves are objects. This provides semantics for
|
|||
|
importing and renaming. Unlike C++ and Modula-3, built-in types can be used as
|
|||
|
base classes for extension by the user. Also, like in C++, most built-in
|
|||
|
operators with special syntax (arithmetic operators, subscripting etc.) can be
|
|||
|
redefined for class instances.</p>
|
|||
|
<p>(Lacking universally accepted terminology to talk about classes, I will make
|
|||
|
occasional use of Smalltalk and C++ terms. I would use Modula-3 terms, since
|
|||
|
its object-oriented semantics are closer to those of Python than C++, but I
|
|||
|
expect that few readers have heard of it.)</p>
|
|||
|
<div class="section" id="a-word-about-names-and-objects">
|
|||
|
<span id="tut-object"></span><h2>9.1. A Word About Names and Objects<a class="headerlink" href="#a-word-about-names-and-objects" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Objects have individuality, and multiple names (in multiple scopes) can be bound
|
|||
|
to the same object. This is known as aliasing in other languages. This is
|
|||
|
usually not appreciated on a first glance at Python, and can be safely ignored
|
|||
|
when dealing with immutable basic types (numbers, strings, tuples). However,
|
|||
|
aliasing has a possibly surprising effect on the semantics of Python code
|
|||
|
involving mutable objects such as lists, dictionaries, and most other types.
|
|||
|
This is usually used to the benefit of the program, since aliases behave like
|
|||
|
pointers in some respects. For example, passing an object is cheap since only a
|
|||
|
pointer is passed by the implementation; and if a function modifies an object
|
|||
|
passed as an argument, the caller will see the change — this eliminates the
|
|||
|
need for two different argument passing mechanisms as in Pascal.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="python-scopes-and-namespaces">
|
|||
|
<span id="tut-scopes"></span><h2>9.2. Python Scopes and Namespaces<a class="headerlink" href="#python-scopes-and-namespaces" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Before introducing classes, I first have to tell you something about Python’s
|
|||
|
scope rules. Class definitions play some neat tricks with namespaces, and you
|
|||
|
need to know how scopes and namespaces work to fully understand what’s going on.
|
|||
|
Incidentally, knowledge about this subject is useful for any advanced Python
|
|||
|
programmer.</p>
|
|||
|
<p>Let’s begin with some definitions.</p>
|
|||
|
<p>A <em>namespace</em> is a mapping from names to objects. Most namespaces are currently
|
|||
|
implemented as Python dictionaries, but that’s normally not noticeable in any
|
|||
|
way (except for performance), and it may change in the future. Examples of
|
|||
|
namespaces are: the set of built-in names (containing functions such as <a class="reference internal" href="../library/functions.html#abs" title="abs"><code class="xref py py-func docutils literal notranslate"><span class="pre">abs()</span></code></a>, and
|
|||
|
built-in exception names); the global names in a module; and the local names in
|
|||
|
a function invocation. In a sense the set of attributes of an object also form
|
|||
|
a namespace. The important thing to know about namespaces is that there is
|
|||
|
absolutely no relation between names in different namespaces; for instance, two
|
|||
|
different modules may both define a function <code class="docutils literal notranslate"><span class="pre">maximize</span></code> without confusion —
|
|||
|
users of the modules must prefix it with the module name.</p>
|
|||
|
<p>By the way, I use the word <em>attribute</em> for any name following a dot — for
|
|||
|
example, in the expression <code class="docutils literal notranslate"><span class="pre">z.real</span></code>, <code class="docutils literal notranslate"><span class="pre">real</span></code> is an attribute of the object
|
|||
|
<code class="docutils literal notranslate"><span class="pre">z</span></code>. Strictly speaking, references to names in modules are attribute
|
|||
|
references: in the expression <code class="docutils literal notranslate"><span class="pre">modname.funcname</span></code>, <code class="docutils literal notranslate"><span class="pre">modname</span></code> is a module
|
|||
|
object and <code class="docutils literal notranslate"><span class="pre">funcname</span></code> is an attribute of it. In this case there happens to be
|
|||
|
a straightforward mapping between the module’s attributes and the global names
|
|||
|
defined in the module: they share the same namespace! <a class="footnote-reference brackets" href="#id2" id="id1">1</a></p>
|
|||
|
<p>Attributes may be read-only or writable. In the latter case, assignment to
|
|||
|
attributes is possible. Module attributes are writable: you can write
|
|||
|
<code class="docutils literal notranslate"><span class="pre">modname.the_answer</span> <span class="pre">=</span> <span class="pre">42</span></code>. Writable attributes may also be deleted with the
|
|||
|
<a class="reference internal" href="../reference/simple_stmts.html#del"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">del</span></code></a> statement. For example, <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">modname.the_answer</span></code> will remove
|
|||
|
the attribute <code class="xref py py-attr docutils literal notranslate"><span class="pre">the_answer</span></code> from the object named by <code class="docutils literal notranslate"><span class="pre">modname</span></code>.</p>
|
|||
|
<p>Namespaces are created at different moments and have different lifetimes. The
|
|||
|
namespace containing the built-in names is created when the Python interpreter
|
|||
|
starts up, and is never deleted. The global namespace for a module is created
|
|||
|
when the module definition is read in; normally, module namespaces also last
|
|||
|
until the interpreter quits. The statements executed by the top-level
|
|||
|
invocation of the interpreter, either read from a script file or interactively,
|
|||
|
are considered part of a module called <a class="reference internal" href="../library/__main__.html#module-__main__" title="__main__: The environment where the top-level script is run."><code class="xref py py-mod docutils literal notranslate"><span class="pre">__main__</span></code></a>, so they have their own
|
|||
|
global namespace. (The built-in names actually also live in a module; this is
|
|||
|
called <a class="reference internal" href="../library/builtins.html#module-builtins" title="builtins: The module that provides the built-in namespace."><code class="xref py py-mod docutils literal notranslate"><span class="pre">builtins</span></code></a>.)</p>
|
|||
|
<p>The local namespace for a function is created when the function is called, and
|
|||
|
deleted when the function returns or raises an exception that is not handled
|
|||
|
within the function. (Actually, forgetting would be a better way to describe
|
|||
|
what actually happens.) Of course, recursive invocations each have their own
|
|||
|
local namespace.</p>
|
|||
|
<p>A <em>scope</em> is a textual region of a Python program where a namespace is directly
|
|||
|
accessible. “Directly accessible” here means that an unqualified reference to a
|
|||
|
name attempts to find the name in the namespace.</p>
|
|||
|
<p>Although scopes are determined statically, they are used dynamically. At any
|
|||
|
time during execution, there are at least three nested scopes whose namespaces
|
|||
|
are directly accessible:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>the innermost scope, which is searched first, contains the local names</p></li>
|
|||
|
<li><p>the scopes of any enclosing functions, which are searched starting with the
|
|||
|
nearest enclosing scope, contains non-local, but also non-global names</p></li>
|
|||
|
<li><p>the next-to-last scope contains the current module’s global names</p></li>
|
|||
|
<li><p>the outermost scope (searched last) is the namespace containing built-in names</p></li>
|
|||
|
</ul>
|
|||
|
<p>If a name is declared global, then all references and assignments go directly to
|
|||
|
the middle scope containing the module’s global names. To rebind variables
|
|||
|
found outside of the innermost scope, the <a class="reference internal" href="../reference/simple_stmts.html#nonlocal"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">nonlocal</span></code></a> statement can be
|
|||
|
used; if not declared nonlocal, those variables are read-only (an attempt to
|
|||
|
write to such a variable will simply create a <em>new</em> local variable in the
|
|||
|
innermost scope, leaving the identically named outer variable unchanged).</p>
|
|||
|
<p>Usually, the local scope references the local names of the (textually) current
|
|||
|
function. Outside functions, the local scope references the same namespace as
|
|||
|
the global scope: the module’s namespace. Class definitions place yet another
|
|||
|
namespace in the local scope.</p>
|
|||
|
<p>It is important to realize that scopes are determined textually: the global
|
|||
|
scope of a function defined in a module is that module’s namespace, no matter
|
|||
|
from where or by what alias the function is called. On the other hand, the
|
|||
|
actual search for names is done dynamically, at run time — however, the
|
|||
|
language definition is evolving towards static name resolution, at “compile”
|
|||
|
time, so don’t rely on dynamic name resolution! (In fact, local variables are
|
|||
|
already determined statically.)</p>
|
|||
|
<p>A special quirk of Python is that – if no <a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> statement is in
|
|||
|
effect – assignments to names always go into the innermost scope. Assignments
|
|||
|
do not copy data — they just bind names to objects. The same is true for
|
|||
|
deletions: the statement <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">x</span></code> removes the binding of <code class="docutils literal notranslate"><span class="pre">x</span></code> from the
|
|||
|
namespace referenced by the local scope. In fact, all operations that introduce
|
|||
|
new names use the local scope: in particular, <a class="reference internal" href="../reference/simple_stmts.html#import"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">import</span></code></a> statements and
|
|||
|
function definitions bind the module or function name in the local scope.</p>
|
|||
|
<p>The <a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> statement can be used to indicate that particular
|
|||
|
variables live in the global scope and should be rebound there; the
|
|||
|
<a class="reference internal" href="../reference/simple_stmts.html#nonlocal"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">nonlocal</span></code></a> statement indicates that particular variables live in
|
|||
|
an enclosing scope and should be rebound there.</p>
|
|||
|
<div class="section" id="scopes-and-namespaces-example">
|
|||
|
<span id="tut-scopeexample"></span><h3>9.2.1. Scopes and Namespaces Example<a class="headerlink" href="#scopes-and-namespaces-example" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>This is an example demonstrating how to reference the different scopes and
|
|||
|
namespaces, and how <a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> and <a class="reference internal" href="../reference/simple_stmts.html#nonlocal"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">nonlocal</span></code></a> affect variable
|
|||
|
binding:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">scope_test</span><span class="p">():</span>
|
|||
|
<span class="k">def</span> <span class="nf">do_local</span><span class="p">():</span>
|
|||
|
<span class="n">spam</span> <span class="o">=</span> <span class="s2">"local spam"</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">do_nonlocal</span><span class="p">():</span>
|
|||
|
<span class="k">nonlocal</span> <span class="n">spam</span>
|
|||
|
<span class="n">spam</span> <span class="o">=</span> <span class="s2">"nonlocal spam"</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">do_global</span><span class="p">():</span>
|
|||
|
<span class="k">global</span> <span class="n">spam</span>
|
|||
|
<span class="n">spam</span> <span class="o">=</span> <span class="s2">"global spam"</span>
|
|||
|
|
|||
|
<span class="n">spam</span> <span class="o">=</span> <span class="s2">"test spam"</span>
|
|||
|
<span class="n">do_local</span><span class="p">()</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s2">"After local assignment:"</span><span class="p">,</span> <span class="n">spam</span><span class="p">)</span>
|
|||
|
<span class="n">do_nonlocal</span><span class="p">()</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s2">"After nonlocal assignment:"</span><span class="p">,</span> <span class="n">spam</span><span class="p">)</span>
|
|||
|
<span class="n">do_global</span><span class="p">()</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s2">"After global assignment:"</span><span class="p">,</span> <span class="n">spam</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="n">scope_test</span><span class="p">()</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="s2">"In global scope:"</span><span class="p">,</span> <span class="n">spam</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The output of the example code is:</p>
|
|||
|
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>After local assignment: test spam
|
|||
|
After nonlocal assignment: nonlocal spam
|
|||
|
After global assignment: nonlocal spam
|
|||
|
In global scope: global spam
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Note how the <em>local</em> assignment (which is default) didn’t change <em>scope_test</em>’s
|
|||
|
binding of <em>spam</em>. The <a class="reference internal" href="../reference/simple_stmts.html#nonlocal"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">nonlocal</span></code></a> assignment changed <em>scope_test</em>’s
|
|||
|
binding of <em>spam</em>, and the <a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> assignment changed the module-level
|
|||
|
binding.</p>
|
|||
|
<p>You can also see that there was no previous binding for <em>spam</em> before the
|
|||
|
<a class="reference internal" href="../reference/simple_stmts.html#global"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">global</span></code></a> assignment.</p>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="a-first-look-at-classes">
|
|||
|
<span id="tut-firstclasses"></span><h2>9.3. A First Look at Classes<a class="headerlink" href="#a-first-look-at-classes" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Classes introduce a little bit of new syntax, three new object types, and some
|
|||
|
new semantics.</p>
|
|||
|
<div class="section" id="class-definition-syntax">
|
|||
|
<span id="tut-classdefinition"></span><h3>9.3.1. Class Definition Syntax<a class="headerlink" href="#class-definition-syntax" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The simplest form of class definition looks like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ClassName</span><span class="p">:</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="mi">1</span><span class="o">></span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="n">N</span><span class="o">></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Class definitions, like function definitions (<a class="reference internal" href="../reference/compound_stmts.html#def"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">def</span></code></a> statements) must be
|
|||
|
executed before they have any effect. (You could conceivably place a class
|
|||
|
definition in a branch of an <a class="reference internal" href="../reference/compound_stmts.html#if"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">if</span></code></a> statement, or inside a function.)</p>
|
|||
|
<p>In practice, the statements inside a class definition will usually be function
|
|||
|
definitions, but other statements are allowed, and sometimes useful — we’ll
|
|||
|
come back to this later. The function definitions inside a class normally have
|
|||
|
a peculiar form of argument list, dictated by the calling conventions for
|
|||
|
methods — again, this is explained later.</p>
|
|||
|
<p>When a class definition is entered, a new namespace is created, and used as the
|
|||
|
local scope — thus, all assignments to local variables go into this new
|
|||
|
namespace. In particular, function definitions bind the name of the new
|
|||
|
function here.</p>
|
|||
|
<p>When a class definition is left normally (via the end), a <em>class object</em> is
|
|||
|
created. This is basically a wrapper around the contents of the namespace
|
|||
|
created by the class definition; we’ll learn more about class objects in the
|
|||
|
next section. The original local scope (the one in effect just before the class
|
|||
|
definition was entered) is reinstated, and the class object is bound here to the
|
|||
|
class name given in the class definition header (<code class="xref py py-class docutils literal notranslate"><span class="pre">ClassName</span></code> in the
|
|||
|
example).</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="class-objects">
|
|||
|
<span id="tut-classobjects"></span><h3>9.3.2. Class Objects<a class="headerlink" href="#class-objects" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Class objects support two kinds of operations: attribute references and
|
|||
|
instantiation.</p>
|
|||
|
<p><em>Attribute references</em> use the standard syntax used for all attribute references
|
|||
|
in Python: <code class="docutils literal notranslate"><span class="pre">obj.name</span></code>. Valid attribute names are all the names that were in
|
|||
|
the class’s namespace when the class object was created. So, if the class
|
|||
|
definition looked like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyClass</span><span class="p">:</span>
|
|||
|
<span class="sd">"""A simple example class"""</span>
|
|||
|
<span class="n">i</span> <span class="o">=</span> <span class="mi">12345</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="s1">'hello world'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>then <code class="docutils literal notranslate"><span class="pre">MyClass.i</span></code> and <code class="docutils literal notranslate"><span class="pre">MyClass.f</span></code> are valid attribute references, returning
|
|||
|
an integer and a function object, respectively. Class attributes can also be
|
|||
|
assigned to, so you can change the value of <code class="docutils literal notranslate"><span class="pre">MyClass.i</span></code> by assignment.
|
|||
|
<code class="xref py py-attr docutils literal notranslate"><span class="pre">__doc__</span></code> is also a valid attribute, returning the docstring belonging to
|
|||
|
the class: <code class="docutils literal notranslate"><span class="pre">"A</span> <span class="pre">simple</span> <span class="pre">example</span> <span class="pre">class"</span></code>.</p>
|
|||
|
<p>Class <em>instantiation</em> uses function notation. Just pretend that the class
|
|||
|
object is a parameterless function that returns a new instance of the class.
|
|||
|
For example (assuming the above class):</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>creates a new <em>instance</em> of the class and assigns this object to the local
|
|||
|
variable <code class="docutils literal notranslate"><span class="pre">x</span></code>.</p>
|
|||
|
<p>The instantiation operation (“calling” a class object) creates an empty object.
|
|||
|
Many classes like to create objects with instances customized to a specific
|
|||
|
initial state. Therefore a class may define a special method named
|
|||
|
<a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a>, like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When a class defines an <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> method, class instantiation
|
|||
|
automatically invokes <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> for the newly-created class instance. So
|
|||
|
in this example, a new, initialized instance can be obtained by:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="o">=</span> <span class="n">MyClass</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Of course, the <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a> method may have arguments for greater
|
|||
|
flexibility. In that case, arguments given to the class instantiation operator
|
|||
|
are passed on to <a class="reference internal" href="../reference/datamodel.html#object.__init__" title="object.__init__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code></a>. For example,</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Complex</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">realpart</span><span class="p">,</span> <span class="n">imagpart</span><span class="p">):</span>
|
|||
|
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">r</span> <span class="o">=</span> <span class="n">realpart</span>
|
|||
|
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">i</span> <span class="o">=</span> <span class="n">imagpart</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="gp">>>> </span><span class="n">x</span> <span class="o">=</span> <span class="n">Complex</span><span class="p">(</span><span class="mf">3.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">4.5</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">x</span><span class="o">.</span><span class="n">r</span><span class="p">,</span> <span class="n">x</span><span class="o">.</span><span class="n">i</span>
|
|||
|
<span class="go">(3.0, -4.5)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="instance-objects">
|
|||
|
<span id="tut-instanceobjects"></span><h3>9.3.3. Instance Objects<a class="headerlink" href="#instance-objects" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Now what can we do with instance objects? The only operations understood by
|
|||
|
instance objects are attribute references. There are two kinds of valid
|
|||
|
attribute names, data attributes and methods.</p>
|
|||
|
<p><em>data attributes</em> correspond to “instance variables” in Smalltalk, and to “data
|
|||
|
members” in C++. Data attributes need not be declared; like local variables,
|
|||
|
they spring into existence when they are first assigned to. For example, if
|
|||
|
<code class="docutils literal notranslate"><span class="pre">x</span></code> is the instance of <code class="xref py py-class docutils literal notranslate"><span class="pre">MyClass</span></code> created above, the following piece of
|
|||
|
code will print the value <code class="docutils literal notranslate"><span class="pre">16</span></code>, without leaving a trace:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span><span class="o">.</span><span class="n">counter</span> <span class="o">=</span> <span class="mi">1</span>
|
|||
|
<span class="k">while</span> <span class="n">x</span><span class="o">.</span><span class="n">counter</span> <span class="o"><</span> <span class="mi">10</span><span class="p">:</span>
|
|||
|
<span class="n">x</span><span class="o">.</span><span class="n">counter</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">counter</span> <span class="o">*</span> <span class="mi">2</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">counter</span><span class="p">)</span>
|
|||
|
<span class="k">del</span> <span class="n">x</span><span class="o">.</span><span class="n">counter</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The other kind of instance attribute reference is a <em>method</em>. A method is a
|
|||
|
function that “belongs to” an object. (In Python, the term method is not unique
|
|||
|
to class instances: other object types can have methods as well. For example,
|
|||
|
list objects have methods called append, insert, remove, sort, and so on.
|
|||
|
However, in the following discussion, we’ll use the term method exclusively to
|
|||
|
mean methods of class instance objects, unless explicitly stated otherwise.)</p>
|
|||
|
<p id="index-0">Valid method names of an instance object depend on its class. By definition,
|
|||
|
all attributes of a class that are function objects define corresponding
|
|||
|
methods of its instances. So in our example, <code class="docutils literal notranslate"><span class="pre">x.f</span></code> is a valid method
|
|||
|
reference, since <code class="docutils literal notranslate"><span class="pre">MyClass.f</span></code> is a function, but <code class="docutils literal notranslate"><span class="pre">x.i</span></code> is not, since
|
|||
|
<code class="docutils literal notranslate"><span class="pre">MyClass.i</span></code> is not. But <code class="docutils literal notranslate"><span class="pre">x.f</span></code> is not the same thing as <code class="docutils literal notranslate"><span class="pre">MyClass.f</span></code> — it
|
|||
|
is a <em>method object</em>, not a function object.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="method-objects">
|
|||
|
<span id="tut-methodobjects"></span><h3>9.3.4. Method Objects<a class="headerlink" href="#method-objects" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Usually, a method is called right after it is bound:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">x</span><span class="o">.</span><span class="n">f</span><span class="p">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In the <code class="xref py py-class docutils literal notranslate"><span class="pre">MyClass</span></code> example, this will return the string <code class="docutils literal notranslate"><span class="pre">'hello</span> <span class="pre">world'</span></code>.
|
|||
|
However, it is not necessary to call a method right away: <code class="docutils literal notranslate"><span class="pre">x.f</span></code> is a method
|
|||
|
object, and can be stored away and called at a later time. For example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">xf</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">f</span>
|
|||
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">xf</span><span class="p">())</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>will continue to print <code class="docutils literal notranslate"><span class="pre">hello</span> <span class="pre">world</span></code> until the end of time.</p>
|
|||
|
<p>What exactly happens when a method is called? You may have noticed that
|
|||
|
<code class="docutils literal notranslate"><span class="pre">x.f()</span></code> was called without an argument above, even though the function
|
|||
|
definition for <code class="xref py py-meth docutils literal notranslate"><span class="pre">f()</span></code> specified an argument. What happened to the argument?
|
|||
|
Surely Python raises an exception when a function that requires an argument is
|
|||
|
called without any — even if the argument isn’t actually used…</p>
|
|||
|
<p>Actually, you may have guessed the answer: the special thing about methods is
|
|||
|
that the instance object is passed as the first argument of the function. In our
|
|||
|
example, the call <code class="docutils literal notranslate"><span class="pre">x.f()</span></code> is exactly equivalent to <code class="docutils literal notranslate"><span class="pre">MyClass.f(x)</span></code>. In
|
|||
|
general, calling a method with a list of <em>n</em> arguments is equivalent to calling
|
|||
|
the corresponding function with an argument list that is created by inserting
|
|||
|
the method’s instance object before the first argument.</p>
|
|||
|
<p>If you still don’t understand how methods work, a look at the implementation can
|
|||
|
perhaps clarify matters. When a non-data attribute of an instance is
|
|||
|
referenced, the instance’s class is searched. If the name denotes a valid class
|
|||
|
attribute that is a function object, a method object is created by packing
|
|||
|
(pointers to) the instance object and the function object just found together in
|
|||
|
an abstract object: this is the method object. When the method object is called
|
|||
|
with an argument list, a new argument list is constructed from the instance
|
|||
|
object and the argument list, and the function object is called with this new
|
|||
|
argument list.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="class-and-instance-variables">
|
|||
|
<span id="tut-class-and-instance-variables"></span><h3>9.3.5. Class and Instance Variables<a class="headerlink" href="#class-and-instance-variables" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Generally speaking, instance variables are for data unique to each instance
|
|||
|
and class variables are for attributes and methods shared by all instances
|
|||
|
of the class:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dog</span><span class="p">:</span>
|
|||
|
|
|||
|
<span class="n">kind</span> <span class="o">=</span> <span class="s1">'canine'</span> <span class="c1"># class variable shared by all instances</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="c1"># instance variable unique to each instance</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="n">d</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Fido'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Buddy'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">kind</span> <span class="c1"># shared by all dogs</span>
|
|||
|
<span class="s1">'canine'</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span><span class="o">.</span><span class="n">kind</span> <span class="c1"># shared by all dogs</span>
|
|||
|
<span class="s1">'canine'</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">name</span> <span class="c1"># unique to d</span>
|
|||
|
<span class="s1">'Fido'</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span><span class="o">.</span><span class="n">name</span> <span class="c1"># unique to e</span>
|
|||
|
<span class="s1">'Buddy'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>As discussed in <a class="reference internal" href="#tut-object"><span class="std std-ref">A Word About Names and Objects</span></a>, shared data can have possibly surprising
|
|||
|
effects with involving <a class="reference internal" href="../glossary.html#term-mutable"><span class="xref std std-term">mutable</span></a> objects such as lists and dictionaries.
|
|||
|
For example, the <em>tricks</em> list in the following code should not be used as a
|
|||
|
class variable because just a single list would be shared by all <em>Dog</em>
|
|||
|
instances:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dog</span><span class="p">:</span>
|
|||
|
|
|||
|
<span class="n">tricks</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># mistaken use of a class variable</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">add_trick</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">trick</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">tricks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">trick</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="n">d</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Fido'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Buddy'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">add_trick</span><span class="p">(</span><span class="s1">'roll over'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span><span class="o">.</span><span class="n">add_trick</span><span class="p">(</span><span class="s1">'play dead'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">tricks</span> <span class="c1"># unexpectedly shared by all dogs</span>
|
|||
|
<span class="p">[</span><span class="s1">'roll over'</span><span class="p">,</span> <span class="s1">'play dead'</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Correct design of the class should use an instance variable instead:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dog</span><span class="p">:</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">tricks</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># creates a new empty list for each dog</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">add_trick</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">trick</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">tricks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">trick</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="o">>>></span> <span class="n">d</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Fido'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span> <span class="o">=</span> <span class="n">Dog</span><span class="p">(</span><span class="s1">'Buddy'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">add_trick</span><span class="p">(</span><span class="s1">'roll over'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span><span class="o">.</span><span class="n">add_trick</span><span class="p">(</span><span class="s1">'play dead'</span><span class="p">)</span>
|
|||
|
<span class="o">>>></span> <span class="n">d</span><span class="o">.</span><span class="n">tricks</span>
|
|||
|
<span class="p">[</span><span class="s1">'roll over'</span><span class="p">]</span>
|
|||
|
<span class="o">>>></span> <span class="n">e</span><span class="o">.</span><span class="n">tricks</span>
|
|||
|
<span class="p">[</span><span class="s1">'play dead'</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="random-remarks">
|
|||
|
<span id="tut-remarks"></span><h2>9.4. Random Remarks<a class="headerlink" href="#random-remarks" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Data attributes override method attributes with the same name; to avoid
|
|||
|
accidental name conflicts, which may cause hard-to-find bugs in large programs,
|
|||
|
it is wise to use some kind of convention that minimizes the chance of
|
|||
|
conflicts. Possible conventions include capitalizing method names, prefixing
|
|||
|
data attribute names with a small unique string (perhaps just an underscore), or
|
|||
|
using verbs for methods and nouns for data attributes.</p>
|
|||
|
<p>Data attributes may be referenced by methods as well as by ordinary users
|
|||
|
(“clients”) of an object. In other words, classes are not usable to implement
|
|||
|
pure abstract data types. In fact, nothing in Python makes it possible to
|
|||
|
enforce data hiding — it is all based upon convention. (On the other hand,
|
|||
|
the Python implementation, written in C, can completely hide implementation
|
|||
|
details and control access to an object if necessary; this can be used by
|
|||
|
extensions to Python written in C.)</p>
|
|||
|
<p>Clients should use data attributes with care — clients may mess up invariants
|
|||
|
maintained by the methods by stamping on their data attributes. Note that
|
|||
|
clients may add data attributes of their own to an instance object without
|
|||
|
affecting the validity of the methods, as long as name conflicts are avoided —
|
|||
|
again, a naming convention can save a lot of headaches here.</p>
|
|||
|
<p>There is no shorthand for referencing data attributes (or other methods!) from
|
|||
|
within methods. I find that this actually increases the readability of methods:
|
|||
|
there is no chance of confusing local variables and instance variables when
|
|||
|
glancing through a method.</p>
|
|||
|
<p>Often, the first argument of a method is called <code class="docutils literal notranslate"><span class="pre">self</span></code>. This is nothing more
|
|||
|
than a convention: the name <code class="docutils literal notranslate"><span class="pre">self</span></code> has absolutely no special meaning to
|
|||
|
Python. Note, however, that by not following the convention your code may be
|
|||
|
less readable to other Python programmers, and it is also conceivable that a
|
|||
|
<em>class browser</em> program might be written that relies upon such a convention.</p>
|
|||
|
<p>Any function object that is a class attribute defines a method for instances of
|
|||
|
that class. It is not necessary that the function definition is textually
|
|||
|
enclosed in the class definition: assigning a function object to a local
|
|||
|
variable in the class is also ok. For example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Function defined outside the class</span>
|
|||
|
<span class="k">def</span> <span class="nf">f1</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="nb">min</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">C</span><span class="p">:</span>
|
|||
|
<span class="n">f</span> <span class="o">=</span> <span class="n">f1</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="s1">'hello world'</span>
|
|||
|
|
|||
|
<span class="n">h</span> <span class="o">=</span> <span class="n">g</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Now <code class="docutils literal notranslate"><span class="pre">f</span></code>, <code class="docutils literal notranslate"><span class="pre">g</span></code> and <code class="docutils literal notranslate"><span class="pre">h</span></code> are all attributes of class <code class="xref py py-class docutils literal notranslate"><span class="pre">C</span></code> that refer to
|
|||
|
function objects, and consequently they are all methods of instances of
|
|||
|
<code class="xref py py-class docutils literal notranslate"><span class="pre">C</span></code> — <code class="docutils literal notranslate"><span class="pre">h</span></code> being exactly equivalent to <code class="docutils literal notranslate"><span class="pre">g</span></code>. Note that this practice
|
|||
|
usually only serves to confuse the reader of a program.</p>
|
|||
|
<p>Methods may call other methods by using method attributes of the <code class="docutils literal notranslate"><span class="pre">self</span></code>
|
|||
|
argument:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Bag</span><span class="p">:</span>
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">addtwice</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Methods may reference global names in the same way as ordinary functions. The
|
|||
|
global scope associated with a method is the module containing its
|
|||
|
definition. (A class is never used as a global scope.) While one
|
|||
|
rarely encounters a good reason for using global data in a method, there are
|
|||
|
many legitimate uses of the global scope: for one thing, functions and modules
|
|||
|
imported into the global scope can be used by methods, as well as functions and
|
|||
|
classes defined in it. Usually, the class containing the method is itself
|
|||
|
defined in this global scope, and in the next section we’ll find some good
|
|||
|
reasons why a method would want to reference its own class.</p>
|
|||
|
<p>Each value is an object, and therefore has a <em>class</em> (also called its <em>type</em>).
|
|||
|
It is stored as <code class="docutils literal notranslate"><span class="pre">object.__class__</span></code>.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="inheritance">
|
|||
|
<span id="tut-inheritance"></span><h2>9.5. Inheritance<a class="headerlink" href="#inheritance" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Of course, a language feature would not be worthy of the name “class” without
|
|||
|
supporting inheritance. The syntax for a derived class definition looks like
|
|||
|
this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">DerivedClassName</span><span class="p">(</span><span class="n">BaseClassName</span><span class="p">):</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="mi">1</span><span class="o">></span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="n">N</span><span class="o">></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The name <code class="xref py py-class docutils literal notranslate"><span class="pre">BaseClassName</span></code> must be defined in a scope containing the
|
|||
|
derived class definition. In place of a base class name, other arbitrary
|
|||
|
expressions are also allowed. This can be useful, for example, when the base
|
|||
|
class is defined in another module:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">DerivedClassName</span><span class="p">(</span><span class="n">modname</span><span class="o">.</span><span class="n">BaseClassName</span><span class="p">):</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Execution of a derived class definition proceeds the same as for a base class.
|
|||
|
When the class object is constructed, the base class is remembered. This is
|
|||
|
used for resolving attribute references: if a requested attribute is not found
|
|||
|
in the class, the search proceeds to look in the base class. This rule is
|
|||
|
applied recursively if the base class itself is derived from some other class.</p>
|
|||
|
<p>There’s nothing special about instantiation of derived classes:
|
|||
|
<code class="docutils literal notranslate"><span class="pre">DerivedClassName()</span></code> creates a new instance of the class. Method references
|
|||
|
are resolved as follows: the corresponding class attribute is searched,
|
|||
|
descending down the chain of base classes if necessary, and the method reference
|
|||
|
is valid if this yields a function object.</p>
|
|||
|
<p>Derived classes may override methods of their base classes. Because methods
|
|||
|
have no special privileges when calling other methods of the same object, a
|
|||
|
method of a base class that calls another method defined in the same base class
|
|||
|
may end up calling a method of a derived class that overrides it. (For C++
|
|||
|
programmers: all methods in Python are effectively <code class="docutils literal notranslate"><span class="pre">virtual</span></code>.)</p>
|
|||
|
<p>An overriding method in a derived class may in fact want to extend rather than
|
|||
|
simply replace the base class method of the same name. There is a simple way to
|
|||
|
call the base class method directly: just call <code class="docutils literal notranslate"><span class="pre">BaseClassName.methodname(self,</span>
|
|||
|
<span class="pre">arguments)</span></code>. This is occasionally useful to clients as well. (Note that this
|
|||
|
only works if the base class is accessible as <code class="docutils literal notranslate"><span class="pre">BaseClassName</span></code> in the global
|
|||
|
scope.)</p>
|
|||
|
<p>Python has two built-in functions that work with inheritance:</p>
|
|||
|
<ul class="simple">
|
|||
|
<li><p>Use <a class="reference internal" href="../library/functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> to check an instance’s type: <code class="docutils literal notranslate"><span class="pre">isinstance(obj,</span> <span class="pre">int)</span></code>
|
|||
|
will be <code class="docutils literal notranslate"><span class="pre">True</span></code> only if <code class="docutils literal notranslate"><span class="pre">obj.__class__</span></code> is <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> or some class
|
|||
|
derived from <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>.</p></li>
|
|||
|
<li><p>Use <a class="reference internal" href="../library/functions.html#issubclass" title="issubclass"><code class="xref py py-func docutils literal notranslate"><span class="pre">issubclass()</span></code></a> to check class inheritance: <code class="docutils literal notranslate"><span class="pre">issubclass(bool,</span> <span class="pre">int)</span></code>
|
|||
|
is <code class="docutils literal notranslate"><span class="pre">True</span></code> since <a class="reference internal" href="../library/functions.html#bool" title="bool"><code class="xref py py-class docutils literal notranslate"><span class="pre">bool</span></code></a> is a subclass of <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>. However,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">issubclass(float,</span> <span class="pre">int)</span></code> is <code class="docutils literal notranslate"><span class="pre">False</span></code> since <a class="reference internal" href="../library/functions.html#float" title="float"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a> is not a
|
|||
|
subclass of <a class="reference internal" href="../library/functions.html#int" title="int"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>.</p></li>
|
|||
|
</ul>
|
|||
|
<div class="section" id="multiple-inheritance">
|
|||
|
<span id="tut-multiple"></span><h3>9.5.1. Multiple Inheritance<a class="headerlink" href="#multiple-inheritance" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Python supports a form of multiple inheritance as well. A class definition with
|
|||
|
multiple base classes looks like this:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">DerivedClassName</span><span class="p">(</span><span class="n">Base1</span><span class="p">,</span> <span class="n">Base2</span><span class="p">,</span> <span class="n">Base3</span><span class="p">):</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="mi">1</span><span class="o">></span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o">.</span>
|
|||
|
<span class="o"><</span><span class="n">statement</span><span class="o">-</span><span class="n">N</span><span class="o">></span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>For most purposes, in the simplest cases, you can think of the search for
|
|||
|
attributes inherited from a parent class as depth-first, left-to-right, not
|
|||
|
searching twice in the same class where there is an overlap in the hierarchy.
|
|||
|
Thus, if an attribute is not found in <code class="xref py py-class docutils literal notranslate"><span class="pre">DerivedClassName</span></code>, it is searched
|
|||
|
for in <code class="xref py py-class docutils literal notranslate"><span class="pre">Base1</span></code>, then (recursively) in the base classes of <code class="xref py py-class docutils literal notranslate"><span class="pre">Base1</span></code>,
|
|||
|
and if it was not found there, it was searched for in <code class="xref py py-class docutils literal notranslate"><span class="pre">Base2</span></code>, and so on.</p>
|
|||
|
<p>In fact, it is slightly more complex than that; the method resolution order
|
|||
|
changes dynamically to support cooperative calls to <a class="reference internal" href="../library/functions.html#super" title="super"><code class="xref py py-func docutils literal notranslate"><span class="pre">super()</span></code></a>. This
|
|||
|
approach is known in some other multiple-inheritance languages as
|
|||
|
call-next-method and is more powerful than the super call found in
|
|||
|
single-inheritance languages.</p>
|
|||
|
<p>Dynamic ordering is necessary because all cases of multiple inheritance exhibit
|
|||
|
one or more diamond relationships (where at least one of the parent classes
|
|||
|
can be accessed through multiple paths from the bottommost class). For example,
|
|||
|
all classes inherit from <a class="reference internal" href="../library/functions.html#object" title="object"><code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></a>, so any case of multiple inheritance
|
|||
|
provides more than one path to reach <a class="reference internal" href="../library/functions.html#object" title="object"><code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></a>. To keep the base classes
|
|||
|
from being accessed more than once, the dynamic algorithm linearizes the search
|
|||
|
order in a way that preserves the left-to-right ordering specified in each
|
|||
|
class, that calls each parent only once, and that is monotonic (meaning that a
|
|||
|
class can be subclassed without affecting the precedence order of its parents).
|
|||
|
Taken together, these properties make it possible to design reliable and
|
|||
|
extensible classes with multiple inheritance. For more detail, see
|
|||
|
<a class="reference external" href="https://www.python.org/download/releases/2.3/mro/">https://www.python.org/download/releases/2.3/mro/</a>.</p>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="private-variables">
|
|||
|
<span id="tut-private"></span><h2>9.6. Private Variables<a class="headerlink" href="#private-variables" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>“Private” instance variables that cannot be accessed except from inside an
|
|||
|
object don’t exist in Python. However, there is a convention that is followed
|
|||
|
by most Python code: a name prefixed with an underscore (e.g. <code class="docutils literal notranslate"><span class="pre">_spam</span></code>) should
|
|||
|
be treated as a non-public part of the API (whether it is a function, a method
|
|||
|
or a data member). It should be considered an implementation detail and subject
|
|||
|
to change without notice.</p>
|
|||
|
<p id="index-1">Since there is a valid use-case for class-private members (namely to avoid name
|
|||
|
clashes of names with names defined by subclasses), there is limited support for
|
|||
|
such a mechanism, called <em class="dfn">name mangling</em>. Any identifier of the form
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__spam</span></code> (at least two leading underscores, at most one trailing underscore)
|
|||
|
is textually replaced with <code class="docutils literal notranslate"><span class="pre">_classname__spam</span></code>, where <code class="docutils literal notranslate"><span class="pre">classname</span></code> is the
|
|||
|
current class name with leading underscore(s) stripped. This mangling is done
|
|||
|
without regard to the syntactic position of the identifier, as long as it
|
|||
|
occurs within the definition of a class.</p>
|
|||
|
<p>Name mangling is helpful for letting subclasses override methods without
|
|||
|
breaking intraclass method calls. For example:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Mapping</span><span class="p">:</span>
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">iterable</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">items_list</span> <span class="o">=</span> <span class="p">[]</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">__update</span><span class="p">(</span><span class="n">iterable</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">iterable</span><span class="p">):</span>
|
|||
|
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">iterable</span><span class="p">:</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">items_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="n">__update</span> <span class="o">=</span> <span class="n">update</span> <span class="c1"># private copy of original update() method</span>
|
|||
|
|
|||
|
<span class="k">class</span> <span class="nc">MappingSubclass</span><span class="p">(</span><span class="n">Mapping</span><span class="p">):</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">keys</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|||
|
<span class="c1"># provides new signature for update()</span>
|
|||
|
<span class="c1"># but does not break __init__()</span>
|
|||
|
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">keys</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">items_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The above example would work even if <code class="docutils literal notranslate"><span class="pre">MappingSubclass</span></code> were to introduce a
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__update</span></code> identifier since it is replaced with <code class="docutils literal notranslate"><span class="pre">_Mapping__update</span></code> in the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">Mapping</span></code> class and <code class="docutils literal notranslate"><span class="pre">_MappingSubclass__update</span></code> in the <code class="docutils literal notranslate"><span class="pre">MappingSubclass</span></code>
|
|||
|
class respectively.</p>
|
|||
|
<p>Note that the mangling rules are designed mostly to avoid accidents; it still is
|
|||
|
possible to access or modify a variable that is considered private. This can
|
|||
|
even be useful in special circumstances, such as in the debugger.</p>
|
|||
|
<p>Notice that code passed to <code class="docutils literal notranslate"><span class="pre">exec()</span></code> or <code class="docutils literal notranslate"><span class="pre">eval()</span></code> does not consider the
|
|||
|
classname of the invoking class to be the current class; this is similar to the
|
|||
|
effect of the <code class="docutils literal notranslate"><span class="pre">global</span></code> statement, the effect of which is likewise restricted
|
|||
|
to code that is byte-compiled together. The same restriction applies to
|
|||
|
<code class="docutils literal notranslate"><span class="pre">getattr()</span></code>, <code class="docutils literal notranslate"><span class="pre">setattr()</span></code> and <code class="docutils literal notranslate"><span class="pre">delattr()</span></code>, as well as when referencing
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__dict__</span></code> directly.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="odds-and-ends">
|
|||
|
<span id="tut-odds"></span><h2>9.7. Odds and Ends<a class="headerlink" href="#odds-and-ends" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Sometimes it is useful to have a data type similar to the Pascal “record” or C
|
|||
|
“struct”, bundling together a few named data items. An empty class definition
|
|||
|
will do nicely:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Employee</span><span class="p">:</span>
|
|||
|
<span class="k">pass</span>
|
|||
|
|
|||
|
<span class="n">john</span> <span class="o">=</span> <span class="n">Employee</span><span class="p">()</span> <span class="c1"># Create an empty employee record</span>
|
|||
|
|
|||
|
<span class="c1"># Fill the fields of the record</span>
|
|||
|
<span class="n">john</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s1">'John Doe'</span>
|
|||
|
<span class="n">john</span><span class="o">.</span><span class="n">dept</span> <span class="o">=</span> <span class="s1">'computer lab'</span>
|
|||
|
<span class="n">john</span><span class="o">.</span><span class="n">salary</span> <span class="o">=</span> <span class="mi">1000</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>A piece of Python code that expects a particular abstract data type can often be
|
|||
|
passed a class that emulates the methods of that data type instead. For
|
|||
|
instance, if you have a function that formats some data from a file object, you
|
|||
|
can define a class with methods <code class="xref py py-meth docutils literal notranslate"><span class="pre">read()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">readline()</span></code> that get the
|
|||
|
data from a string buffer instead, and pass it as an argument.</p>
|
|||
|
<p>Instance method objects have attributes, too: <code class="docutils literal notranslate"><span class="pre">m.__self__</span></code> is the instance
|
|||
|
object with the method <code class="xref py py-meth docutils literal notranslate"><span class="pre">m()</span></code>, and <code class="docutils literal notranslate"><span class="pre">m.__func__</span></code> is the function object
|
|||
|
corresponding to the method.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="iterators">
|
|||
|
<span id="tut-iterators"></span><h2>9.8. Iterators<a class="headerlink" href="#iterators" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>By now you have probably noticed that most container objects can be looped over
|
|||
|
using a <a class="reference internal" href="../reference/compound_stmts.html#for"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">for</span></code></a> statement:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]:</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
|
|||
|
<span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
|
|||
|
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="p">{</span><span class="s1">'one'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'two'</span><span class="p">:</span><span class="mi">2</span><span class="p">}:</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|||
|
<span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="s2">"123"</span><span class="p">:</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
|
|||
|
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"myfile.txt"</span><span class="p">):</span>
|
|||
|
<span class="nb">print</span><span class="p">(</span><span class="n">line</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This style of access is clear, concise, and convenient. The use of iterators
|
|||
|
pervades and unifies Python. Behind the scenes, the <a class="reference internal" href="../reference/compound_stmts.html#for"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">for</span></code></a> statement
|
|||
|
calls <a class="reference internal" href="../library/functions.html#iter" title="iter"><code class="xref py py-func docutils literal notranslate"><span class="pre">iter()</span></code></a> on the container object. The function returns an iterator
|
|||
|
object that defines the method <a class="reference internal" href="../library/stdtypes.html#iterator.__next__" title="iterator.__next__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code></a> which accesses
|
|||
|
elements in the container one at a time. When there are no more elements,
|
|||
|
<a class="reference internal" href="../library/stdtypes.html#iterator.__next__" title="iterator.__next__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code></a> raises a <a class="reference internal" href="../library/exceptions.html#StopIteration" title="StopIteration"><code class="xref py py-exc docutils literal notranslate"><span class="pre">StopIteration</span></code></a> exception which tells the
|
|||
|
<code class="xref std std-keyword docutils literal notranslate"><span class="pre">for</span></code> loop to terminate. You can call the <a class="reference internal" href="../library/stdtypes.html#iterator.__next__" title="iterator.__next__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code></a> method
|
|||
|
using the <a class="reference internal" href="../library/functions.html#next" title="next"><code class="xref py py-func docutils literal notranslate"><span class="pre">next()</span></code></a> built-in function; this example shows how it all works:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s1">'abc'</span>
|
|||
|
<span class="gp">>>> </span><span class="n">it</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">it</span>
|
|||
|
<span class="go"><iterator object at 0x00A1DB50></span>
|
|||
|
<span class="gp">>>> </span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
|||
|
<span class="go">'a'</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
|||
|
<span class="go">'b'</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
|||
|
<span class="go">'c'</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
|||
|
<span class="gt">Traceback (most recent call last):</span>
|
|||
|
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
|
|||
|
<span class="nb">next</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
|
|||
|
<span class="gr">StopIteration</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Having seen the mechanics behind the iterator protocol, it is easy to add
|
|||
|
iterator behavior to your classes. Define an <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__iter__()</span></code></a> method which
|
|||
|
returns an object with a <a class="reference internal" href="../library/stdtypes.html#iterator.__next__" title="iterator.__next__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code></a> method. If the class
|
|||
|
defines <code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code>, then <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__iter__()</span></code></a> can just return <code class="docutils literal notranslate"><span class="pre">self</span></code>:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Reverse</span><span class="p">:</span>
|
|||
|
<span class="sd">"""Iterator for looping over a sequence backwards."""</span>
|
|||
|
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">data</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">return</span> <span class="bp">self</span>
|
|||
|
|
|||
|
<span class="k">def</span> <span class="nf">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
|
|||
|
<span class="k">raise</span> <span class="ne">StopIteration</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">-</span> <span class="mi">1</span>
|
|||
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">rev</span> <span class="o">=</span> <span class="n">Reverse</span><span class="p">(</span><span class="s1">'spam'</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">iter</span><span class="p">(</span><span class="n">rev</span><span class="p">)</span>
|
|||
|
<span class="go"><__main__.Reverse object at 0x00A1DB50></span>
|
|||
|
<span class="gp">>>> </span><span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">rev</span><span class="p">:</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">m</span>
|
|||
|
<span class="go">a</span>
|
|||
|
<span class="go">p</span>
|
|||
|
<span class="go">s</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="generators">
|
|||
|
<span id="tut-generators"></span><h2>9.9. Generators<a class="headerlink" href="#generators" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p><a class="reference internal" href="../glossary.html#term-generator"><span class="xref std std-term">Generator</span></a>s are a simple and powerful tool for creating iterators. They
|
|||
|
are written like regular functions but use the <a class="reference internal" href="../reference/simple_stmts.html#yield"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">yield</span></code></a> statement
|
|||
|
whenever they want to return data. Each time <a class="reference internal" href="../library/functions.html#next" title="next"><code class="xref py py-func docutils literal notranslate"><span class="pre">next()</span></code></a> is called on it, the
|
|||
|
generator resumes where it left off (it remembers all the data values and which
|
|||
|
statement was last executed). An example shows that generators can be trivially
|
|||
|
easy to create:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
|
|||
|
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
|
|||
|
<span class="k">yield</span> <span class="n">data</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">reverse</span><span class="p">(</span><span class="s1">'golf'</span><span class="p">):</span>
|
|||
|
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">char</span><span class="p">)</span>
|
|||
|
<span class="gp">...</span>
|
|||
|
<span class="go">f</span>
|
|||
|
<span class="go">l</span>
|
|||
|
<span class="go">o</span>
|
|||
|
<span class="go">g</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Anything that can be done with generators can also be done with class-based
|
|||
|
iterators as described in the previous section. What makes generators so
|
|||
|
compact is that the <a class="reference internal" href="../reference/datamodel.html#object.__iter__" title="object.__iter__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__iter__()</span></code></a> and <a class="reference internal" href="../reference/expressions.html#generator.__next__" title="generator.__next__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__next__()</span></code></a> methods
|
|||
|
are created automatically.</p>
|
|||
|
<p>Another key feature is that the local variables and execution state are
|
|||
|
automatically saved between calls. This made the function easier to write and
|
|||
|
much more clear than an approach using instance variables like <code class="docutils literal notranslate"><span class="pre">self.index</span></code>
|
|||
|
and <code class="docutils literal notranslate"><span class="pre">self.data</span></code>.</p>
|
|||
|
<p>In addition to automatic method creation and saving program state, when
|
|||
|
generators terminate, they automatically raise <a class="reference internal" href="../library/exceptions.html#StopIteration" title="StopIteration"><code class="xref py py-exc docutils literal notranslate"><span class="pre">StopIteration</span></code></a>. In
|
|||
|
combination, these features make it easy to create iterators with no more effort
|
|||
|
than writing a regular function.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="generator-expressions">
|
|||
|
<span id="tut-genexps"></span><h2>9.10. Generator Expressions<a class="headerlink" href="#generator-expressions" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Some simple generators can be coded succinctly as expressions using a syntax
|
|||
|
similar to list comprehensions but with parentheses instead of square brackets.
|
|||
|
These expressions are designed for situations where the generator is used right
|
|||
|
away by an enclosing function. Generator expressions are more compact but less
|
|||
|
versatile than full generator definitions and tend to be more memory friendly
|
|||
|
than equivalent list comprehensions.</p>
|
|||
|
<p>Examples:</p>
|
|||
|
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">sum</span><span class="p">(</span><span class="n">i</span><span class="o">*</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span> <span class="c1"># sum of squares</span>
|
|||
|
<span class="go">285</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="n">xvec</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">]</span>
|
|||
|
<span class="gp">>>> </span><span class="n">yvec</span> <span class="o">=</span> <span class="p">[</span><span class="mi">7</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">sum</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">xvec</span><span class="p">,</span> <span class="n">yvec</span><span class="p">))</span> <span class="c1"># dot product</span>
|
|||
|
<span class="go">260</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">math</span> <span class="k">import</span> <span class="n">pi</span><span class="p">,</span> <span class="n">sin</span>
|
|||
|
<span class="gp">>>> </span><span class="n">sine_table</span> <span class="o">=</span> <span class="p">{</span><span class="n">x</span><span class="p">:</span> <span class="n">sin</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">pi</span><span class="o">/</span><span class="mi">180</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">91</span><span class="p">)}</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="n">unique_words</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">word</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">page</span> <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="n">valedictorian</span> <span class="o">=</span> <span class="nb">max</span><span class="p">((</span><span class="n">student</span><span class="o">.</span><span class="n">gpa</span><span class="p">,</span> <span class="n">student</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="k">for</span> <span class="n">student</span> <span class="ow">in</span> <span class="n">graduates</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="s1">'golf'</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">list</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">))</span>
|
|||
|
<span class="go">['f', 'l', 'o', 'g']</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p class="rubric">Footnotes</p>
|
|||
|
<dl class="footnote brackets">
|
|||
|
<dt class="label" id="id2"><span class="brackets"><a class="fn-backref" href="#id1">1</a></span></dt>
|
|||
|
<dd><p>Except for one thing. Module objects have a secret read-only attribute called
|
|||
|
<a class="reference internal" href="../library/stdtypes.html#object.__dict__" title="object.__dict__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__dict__</span></code></a> which returns the dictionary used to implement the module’s
|
|||
|
namespace; the name <a class="reference internal" href="../library/stdtypes.html#object.__dict__" title="object.__dict__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__dict__</span></code></a> is an attribute but not a global name.
|
|||
|
Obviously, using this violates the abstraction of namespace implementation, and
|
|||
|
should be restricted to things like post-mortem debuggers.</p>
|
|||
|
</dd>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|||
|
<div class="sphinxsidebarwrapper">
|
|||
|
<h3><a href="../contents.html">Table of Contents</a></h3>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#">9. Classes</a><ul>
|
|||
|
<li><a class="reference internal" href="#a-word-about-names-and-objects">9.1. A Word About Names and Objects</a></li>
|
|||
|
<li><a class="reference internal" href="#python-scopes-and-namespaces">9.2. Python Scopes and Namespaces</a><ul>
|
|||
|
<li><a class="reference internal" href="#scopes-and-namespaces-example">9.2.1. Scopes and Namespaces Example</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#a-first-look-at-classes">9.3. A First Look at Classes</a><ul>
|
|||
|
<li><a class="reference internal" href="#class-definition-syntax">9.3.1. Class Definition Syntax</a></li>
|
|||
|
<li><a class="reference internal" href="#class-objects">9.3.2. Class Objects</a></li>
|
|||
|
<li><a class="reference internal" href="#instance-objects">9.3.3. Instance Objects</a></li>
|
|||
|
<li><a class="reference internal" href="#method-objects">9.3.4. Method Objects</a></li>
|
|||
|
<li><a class="reference internal" href="#class-and-instance-variables">9.3.5. Class and Instance Variables</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#random-remarks">9.4. Random Remarks</a></li>
|
|||
|
<li><a class="reference internal" href="#inheritance">9.5. Inheritance</a><ul>
|
|||
|
<li><a class="reference internal" href="#multiple-inheritance">9.5.1. Multiple Inheritance</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#private-variables">9.6. Private Variables</a></li>
|
|||
|
<li><a class="reference internal" href="#odds-and-ends">9.7. Odds and Ends</a></li>
|
|||
|
<li><a class="reference internal" href="#iterators">9.8. Iterators</a></li>
|
|||
|
<li><a class="reference internal" href="#generators">9.9. Generators</a></li>
|
|||
|
<li><a class="reference internal" href="#generator-expressions">9.10. Generator Expressions</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h4>Previous topic</h4>
|
|||
|
<p class="topless"><a href="errors.html"
|
|||
|
title="previous chapter">8. Errors and Exceptions</a></p>
|
|||
|
<h4>Next topic</h4>
|
|||
|
<p class="topless"><a href="stdlib.html"
|
|||
|
title="next chapter">10. Brief Tour of the Standard Library</a></p>
|
|||
|
<div role="note" aria-label="source link">
|
|||
|
<h3>This Page</h3>
|
|||
|
<ul class="this-page-menu">
|
|||
|
<li><a href="../bugs.html">Report a Bug</a></li>
|
|||
|
<li>
|
|||
|
<a href="https://github.com/python/cpython/blob/3.7/Doc/tutorial/classes.rst"
|
|||
|
rel="nofollow">Show Source
|
|||
|
</a>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="clearer"></div>
|
|||
|
</div>
|
|||
|
<div class="related" role="navigation" aria-label="related navigation">
|
|||
|
<h3>Navigation</h3>
|
|||
|
<ul>
|
|||
|
<li class="right" style="margin-right: 10px">
|
|||
|
<a href="../genindex.html" title="General Index"
|
|||
|
>index</a></li>
|
|||
|
<li class="right" >
|
|||
|
<a href="../py-modindex.html" title="Python Module Index"
|
|||
|
>modules</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="stdlib.html" title="10. Brief Tour of the Standard Library"
|
|||
|
>next</a> |</li>
|
|||
|
<li class="right" >
|
|||
|
<a href="errors.html" title="8. Errors and Exceptions"
|
|||
|
>previous</a> |</li>
|
|||
|
<li><img src="../_static/py.png" alt=""
|
|||
|
style="vertical-align: middle; margin-top: -1px"/></li>
|
|||
|
<li><a href="https://www.python.org/">Python</a> »</li>
|
|||
|
<li>
|
|||
|
<span class="language_switcher_placeholder">en</span>
|
|||
|
<span class="version_switcher_placeholder">3.7.4</span>
|
|||
|
<a href="../index.html">Documentation </a> »
|
|||
|
</li>
|
|||
|
|
|||
|
<li class="nav-item nav-item-1"><a href="index.html" >The Python Tutorial</a> »</li>
|
|||
|
<li class="right">
|
|||
|
|
|||
|
|
|||
|
<div class="inline-search" style="display: none" role="search">
|
|||
|
<form class="inline-search" action="../search.html" method="get">
|
|||
|
<input placeholder="Quick search" type="text" name="q" />
|
|||
|
<input type="submit" value="Go" />
|
|||
|
<input type="hidden" name="check_keywords" value="yes" />
|
|||
|
<input type="hidden" name="area" value="default" />
|
|||
|
</form>
|
|||
|
</div>
|
|||
|
<script type="text/javascript">$('.inline-search').show(0);</script>
|
|||
|
|
|
|||
|
</li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<div class="footer">
|
|||
|
© <a href="../copyright.html">Copyright</a> 2001-2019, Python Software Foundation.
|
|||
|
<br />
|
|||
|
The Python Software Foundation is a non-profit corporation.
|
|||
|
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
|||
|
<br />
|
|||
|
Last updated on Jul 13, 2019.
|
|||
|
<a href="../bugs.html">Found a bug</a>?
|
|||
|
<br />
|
|||
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.0.1.
|
|||
|
</div>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|