⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node11.html

📁 同样是来自国外的经典python教材
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head>  <title>9. 类别(Classes)</title>    <meta name="description" content="9. 类别(Classes) ">   <meta name="keywords" content="tut">   <meta name="resource-type" content="document">   <meta name="distribution" content="global">   <link rel="STYLESHEET" href="tut.css">   <link rel="next" href="node12.html">   <link rel="previous" href="node10.html">   <link rel="up" href="tut.html">   <link rel="next" href="node12.html"></head> <body> <div class="navigation"><table align="Center" width="100%" cellpadding="0" cellspacing="2"> <tbody>    <tr> <td><a href="node10.html"><img src="../icons/previous.gif" border="0" height="32" alt="Previous Page" width="32"></a></td> <td><a href="tut.html"><img src="../icons/up.gif" border="0" height="32" alt="Up One Level" width="32"></a></td> <td><a href="node12.html"><img src="../icons/next.gif" border="0" height="32" alt="Next Page" width="32"></a></td> <td align="Center" width="100%">Python 教学文件</td> <td><a href="node2.html"><img src="../icons/contents.gif" border="0" height="32" alt="Contents" width="32"></a></td> <td><img src="../icons/blank.gif" border="0" height="32" alt="" width="32"></td> <td><img src="../icons/blank.gif" border="0" height="32" alt="" width="32"></td> </tr>  </tbody></table> <b class="navlabel">Previous:</b> <a class="sectref" href="node10.html">8. 程式错误与例外(Exceptions)情形</a> <b class="navlabel">Up:</b> <a class="sectref" href="tut.html">Python 教学文件</a> <b class="navlabel">Next:</b> <a class="sectref" href="node12.html">10. 现在呢? </a> <br><hr></div> <!--End of Navigation Panel--> <!--Table of Child-Links--> <a name="CHILD_LINKS"><strong>小段落 </strong></a>  <ul>   <li><a name="tex2html356" href="node11.html#SECTION0011100000000000000000">9.1 术语的使用说明 </a> </li>  <li><a name="tex2html357" href="node11.html#SECTION0011200000000000000000">9.2 Python的可用范围(Scopes)及命名空间(Naming Spaces) </a> </li>  <li><a name="tex2html358" href="node11.html#SECTION0011300000000000000000">9.3 Class(类别)初探 </a>     <ul>       <li><a name="tex2html359" href="node11.html#SECTION0011310000000000000000">9.3.1 定义Class(类别)的语法 </a> </li>      <li><a name="tex2html360" href="node11.html#SECTION0011320000000000000000">9.3.2 Class Objects(类别物件) </a> </li>      <li><a name="tex2html361" href="node11.html#SECTION0011330000000000000000">9.3.3 Instance Objects(特例物件) </a> </li>      <li><a name="tex2html362" href="node11.html#SECTION0011340000000000000000">9.3.4 Method Objects(方法物件)  </a> </li>    </ul> </li>  <li><a name="tex2html363" href="node11.html#SECTION0011400000000000000000">9.4 一些随意的想法 </a> </li>  <li><a name="tex2html364" href="node11.html#SECTION0011500000000000000000">9.5 继承 </a>     <ul>       <li><a name="tex2html365" href="node11.html#SECTION0011510000000000000000">9.5.1 多重继承 </a> </li>    </ul> </li>  <li><a name="tex2html366" href="node11.html#SECTION0011600000000000000000">9.6 Private变数 </a> </li>  <li><a name="tex2html367" href="node11.html#SECTION0011700000000000000000">9.7 其它 </a>     <ul>       <li><a name="tex2html368" href="node11.html#SECTION0011710000000000000000">9.7.1 例外(Exceptions)也可以是类别 </a> </li>    </ul>  </li></ul> <!--End of Table of Child-Links--> <hr>  <h1> <br> 9. Class(类别)   </h1>  <p> Python的类别机制在加入最少新的语法及语意的情况下加入了类别的支援。Python的类别机制是C++ 以及Modula-3的综合体。正如同在modules里面的情况一样,Python的class也没有在其定义及使用者之间加入绝对的障碍,而是仰赖使用者有礼貌的不要去闯入其定义之中(not to ``break into the definition'')。对于class来说最重要的一些特性在Python里面都完全的保留:类别的继承可以继承自个基础类别(baseclasses),一个子类别(derived class)可以override其所有基础类别(base class)的任何方法(method),一个method也可以呼叫一个基础类别的同名方法,物件可以自由决定是否要让某些资料是private的。  </p><p> 以C++ 的术语来说,Python所有的类别成员(包含其资料成员)都是  <i>public</i> 的,而且所有的函式成员(memberfunctions)都是 <i>virtual</i> 的。也并没有所谓的建构元(constructors)或是解构元(destructors)的存在。如同在 Modula-3里面一样,从物件的方法(method)里面要使用物件的成员并没有捷径可以使用:成员函式的宣告必须在第一个参数中明白的在表示所存在其中的物件,而此参数在呼叫时是不用传的。如同在Smalltalk里面一样,类别本身也是一个物件,事实上在Python里面,所有的资料型态(datatype)都是物件。这提供了在import以及重新命名时候的语意(sematics)。但是如同在C++ 或是Modula-3里面,内建的基本型态是不能被使用者拿来当作基础类别使用的。与C++类似但不同于Modula-3的是,大部分有特别语法的内建运算元(operators),例如数值运算及subscripting,都可以被拿来在类别中重新定义的。  </p><p>  </p><h1> <br> 9.1 术语的使用说明  </h1>  <p> 由于缺乏普遍性的术语可以讨论类别,我只好偶而从Smalltalk或是C++的术语中借来用。(我其实更想用Modula-3的术语,因为它的术语在语意上比C++还要接近Python,但是我想大部分的读者都没有听过它)。  </p><p> 我也要警告你的是,物件这个字在Python里面不必然指的是类别的一个特例(instance),这是一个在物件导向读者中常见的陷阱。与C++及Modula-3相同但与Smalltalk不同的是,并非所有在Python里面的资料型态都是类别,像是整数及list这类的基本的内建型态就不是类别,甚至一些特别的资料型态像是file都不是类别。无论如何,<i>所有的</i> Python的资料型态都或多或少都有一些基本相同的语意特性,我们可以把这个相同点叫做物件。  </p><p> 物件有其个体性(individuality,独特性),而且你可以用不同的名字连结到同一个物件去,这在其他的程式语言中也叫做别名(aliasing)。通常你第一次看到Python不会觉得这有什么特别,而且你在处理不可变动的(immutable)基本型态(例如数目字,字串及tuple)时,你根本可以不去管它。但是对于一些都可变动的(mutable)物件,像是list,dictioanry以及其他用来表现在程式之外的实体(像是档案及视窗)的资料型别,对它们来说aliasing就和与它们有关之Python程式码语意的解释,有(故意的)一些影响。这样的影响通常是对程式有正面的效益,因为别名(alias)运作的方式就像是一个有礼貌的指标(pointer)。举例来说,当你传一个物件当参数时,因为所传的其实只是一个指标,所以所费的资源就不多。而且,当在函式之内对这个传入的物件进行修改时,在外面呼叫这个函式的人(caller)会看得见函式所做的修改,这大大的简化了在Pascal里面需要两种不同参数传递机制才能作到的事。 </p><p>  </p><h1> <br> 9.2 Python的可用范围(Scopes)及命名空间(Naming Spaces)  </h1>  <p> 在介绍类别(class)之前,我首先必须介绍Python有关可用范围(scope)的一些准则。类别的定义也对命名空间(namespace)做了一些小技巧,所以你需要对scope及namespace的运作有一些了解才能够完全的掌握到底发生了什么事。对于进阶的Python程式设计师来说,有关这个主题的了解是很有帮助的。  </p><p> 现在让我们先来定义一些东西:  </p><p> 一个  <i>namespace</i> 指的是名称与物件的对应关系的组合。目前来说,namespace都是以Python的dictionary来实作出来的,但是这应该没有多大意义(除非对程式的效率),而且在未来可能也有所改变。Namespace的例子有:一组的内建名称(像是<tt class="function">abs()</tt> 的函式,还有内建的exception名称),在module里的全域变数(globalvariables),以及在函式里的local变数。某种意义来说,一个物件里的特性(attributes,译:成员)也组成一个namespace。在这里要知道的重点是,不同的namespace里面所定义的名称是彼此没有任何关系的。举例来说,两个不同的module都可以定义一个叫做``maximize''的函式。这一点都不冲突,因为使用者必须要在这个函式的名称前加上module的名称。  </p><p> 喔,我在这里所用的 <i>attribute</i> 一字指的事所有在点号后面的东西,举例来说在 <code>z.real</code>这个expression里面 <code>real</code> 就是一个属于 <code>z</code> 这个物件的attribute。严格说来,使用module里面的名称也是一个attribute的指称(references),在 <code>modname.funcname</code> 这个expression里面,  <code>modname</code> 就是一个module物件,而 <code>funcname</code> 就是其attribute。在这个例子里面,刚好module的attributes就对应了在module里面定义的全域变数,所以我们就说它们就是在一个namespace里面。 <a name="tex2html5" href="#foot1309"><sup>9.1</sup></a> </p><p> Attributes可以是唯读的或是可改写的。对可改写的attribute,你可以设定值给它。Module的 attributes是可以改写的:所以你可以写"<tt class="samp">modname.the_answer = 42</tt>" 来改变其值。可改写的attributes也可以被删除掉,你可以用<tt class="keyword">del</tt> 叙述像是  "<tt class="samp">del modname.the_answer</tt>" 来做。   </p><p> 命名空间(Name spaces)是在不同的时候被创造出来的,而且其存在的时间也都不一定。内建名称的namespace是在当Python直译器启动时就被创造出来,而且不会被删除掉。Module里全域(global)的namespace是当module的定义被读入的时候就被创造出来,通常在直译器离开之前也不会被删除。那些在top-level启动直译器里面被执行的指令,不管是在互动模式或是从script里面而来的,都隶属于一个叫做 <tt class="module">__main__</tt> 的module,所以它们也算有自己的一个global namespace。 (事实上,内建的名称也都在一个module里面,这个module叫做 <tt class="module">__builtin__</tt> )   </p><p> 函式所有的namespace叫做local namespace,是在函式被呼叫时才创造的,而且当函式传回一个值或是引发一个本身无法处理的exception时,这个namespace就被删除(事实上,也许说遗忘是比较贴切的形容词)。当然,递回的函式呼叫会使每个呼叫都有自己的localnamespace。   </p><p> 一个可用范围( <i>scope</i> )是一个在Python程式里面文字上的范围,在这个范围里面你可以直接使用某个namespace。直接使用(``Directlyaccessible'')的意思是指对一个名称而言不合格的参考(unqualified reference)试图想要在namespace里面找某一个名称。  </p><p> 虽然scope是静态的(statically)被决定的,但是我们使用namescope的时候是很动态(dynamically)的来使用之。在任何一个程式执行的地方,都正好有三层的scope正在被使用(也就是有三个可以直接使用的namespace):首先寻找的是最内圈的scope,包含有local的名称;其次搜寻的是中间一层,包含有目前所在的module的全域名称(globalnames);最后搜寻的是最外面的一层,也就是包含有内建名称的namespace。   </p><p> 通常,local scope指的是在文字上面目前的函式所拥有的local名称。在函式之外的话,local scope就指的是globalscope所指的namespace。类别的定义在local scope里面则又放入了另外的一个namespace。   </p><p> 要注意的是scope的决定是依文字的安排来决定的。一个定义在module里面的函式,其global scope就是module的namespace,不管这个函式是从哪里或是用哪一个别名被呼叫的。在另一方面来说,真正的名称搜寻路线是动态的决定的(在程式执行的时候)。但是Python语言本身的定义好像慢慢的往静态决定变化(也就是在编译的时候),所以,不要过分依赖动态的名称解释。(事实上,local的变数都已经是静态就已经决定了的)。  </p><p> Python有一个很特别的变化就是当设定(assignment)的时候都一定是进入到了最内层的scope。设定并不是复制资料,相反的,它只是把物件及名称连结起来而已。对于删除也是一样的, "<tt class="samp">del x</tt>" 事实上只是把 <code>x</code> 的连结从local scope所代表的namespace中除去。事实上,所有会引进新名称的动作都是使用localscope:特别是, import叙述以及函式的定义就是把module以及函式的名称都连结到local scope里面来了。( <tt class="keyword">global</tt> 这个叙述可以用来特别指定某个特殊的变数是要放在global scope里的)   </p><p>  </p><h1> <br> 9.3 Class(类别)初探   </h1>  <p> 类别(Classes)的观念引进了许多新的语法,三种新的物件以及一些新的语言上的意义:  </p><p>  </p><h2> <br> 9.3.1 定义Class(类别)的语法   </h2>  <p> 最简单的类别定义的形式看起来像是这样的:   </p><p> </p><dl><dd><pre class="verbatim">class ClassName:<br>    &lt;statement-1&gt;<br>    .<br>    .<br>    .<br>    &lt;statement-N&gt;<br></pre>  </dd>  </dl>    <p> 类别的定义与函式的定义(都是用 <tt class="keyword">def</tt> 叙述)相同,都必须在要在它们有任何作用之前就定义好。(你也可以在 <tt class="keyword">if</tt> 叙述或是一个函式里面放入类别的定义)。   </p>  <p> 在实务上,存在于类别定义内的叙述通常都是函式的定义,但是我们也可以放入其他的叙述。这样的做法有时也很好用,我们之后会再会来看这个用法。类别定义内的函式定义通常都有一个特别的参数形式,这是为了method的特别呼叫习俗的。我们还是留到后面再来讨论之。  </p>  <p> 当一个类别的定义进来时,就会创造出一个新的namespace,而且会当作是一个local scope来用。所以所有对local变数的设定都会进入到这个新的namespace里面。具体来说,函式的定义也会把新的函式的名称连结到这里来。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -