📄 node6.html
字号:
<p> </p> <h1> <br> 4.4 <tt class="keyword">break</tt> 及 <tt class="keyword">continue</tt>叙述,以及在回圈中的 <tt class="keyword">else</tt> 子句 </h1> <p> 如同在C语言里一样, <tt class="keyword">break</tt> 叙述中断最靠近的一个 <tt class="keyword">for</tt> 或 <tt class="keyword">while</tt> 回圈。 </p> <p> 同样的,从C语言借过来的 <tt class="keyword">continue</tt> 叙述会中断目前执行的回圈,并且执行下一个循环。 </p> <p> 特别的是,Python的回圈有一个 <code>else</code> 子句,这个子句之后的程式码会在整个回圈正常结束的时候执行,(对 <tt class="keyword">for</tt>) 回圈而言指的是list已经到底,对 <tt class="keyword">while</tt> 回圈而言指的是条件式变成false)。但是,若是在非正常结束(因为 <tt class="keyword">break</tt> 叙述)的情况下 <code>else</code> 子句的程式码就不会执行。底下的例子是一个回圈,用来找出所有的质数: </p> <p> </p> <dl> <dd><pre class="verbatim">>>> for n in range(2, 10):<br>... for x in range(2, n):<br>... if n % x == 0:<br>... print n, 'equals', x, '*', n/x<br>... break<br>... else:<br>... print n, 'is a prime number'<br>... <br>2 is a prime number<br>3 is a prime number<br>4 equals 2 * 2<br>5 is a prime number<br>6 equals 2 * 3<br>7 is a prime number<br>8 equals 2 * 4<br>9 equals 3 * 3<br></pre> </dd> </dl> <p> </p> <h1> <br> 4.5 <tt class="keyword">pass</tt> 叙述 </h1> <p> <tt class="keyword">pass</tt> 叙述什么也不做,通常是用在当你的程式的语法上需要有一个叙述,但是却不需要做任何事的时候。例子如下: </p> <p> </p> <dl> <dd><pre class="verbatim">>>> while 1:<br>... pass # Busy-wait for keyboard interrupt<br>...<br></pre> </dd> </dl> <p> </p> <h1> <br> 4.6 定义函式 </h1> <p> 我们可以定义一个函式,在底下这个函式定义的例子,当我们给定想要印出的范围,这个函式会印出一个费氏数列来: </p> <p> </p> <dl> <dd><pre class="verbatim">>>> def fib(n): # write Fibonacci series up to n<br>... "Print a Fibonacci series up to n"<br>... a, b = 0, 1<br>... while b < n:<br>... print b,<br>... a, b = b, a+b<br>... <br>>>> # Now call the function we just defined:<br>... fib(2000)<br>1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597<br></pre> </dd> </dl> <p> 在上例中这个 <tt class="keyword">def</tt> 关键字代表了一个函式的定义(function <i>definition</i>),在 <tt class="keyword">def</tt> 之后必须接着函式的名称以及一个用括号括起来的一连串的参数。接下来一行之后的程式码就是函式的主体部分,而且必须是缩排的。函式的程式码部分的第一个statement可以是一个字串常数(stringliteral),这个字串常数会被当作是函式的注解部分而叫做注解字串(documentation string或是 <i class="dfn">docstring</i> )。 </p> <p> 有工具可以使用这个注解字串来自动的制作出线上的或是印出来的文件,或者是让使用者可以互动式的浏览程式码。写注解是一个好习惯,所以最好养成这个好习惯,把所有的程式码都写上注解字串。 </p> <p> <i>执行</i>函式的时候会产生一个目前(local)的符号表(system table),这个表是用来记录函式中的所有local的变数的。更精确的来说,所有在函式中变数的设定值都会纪录在这个systemtable中,所以当你要使用(reference)一个变数时,会先检查local的system table,然后是整个程式(global)的systemtalbe,然后是内建的变数名称。虽然 <tt class="keyword">global</tt> 变数可以在函式使用(reference),但是不能在函式之内直接的设定其值(除非是在一个global的statement中建立的)。 </p> <p> 当函式被呼叫时,实际传入的函式参数是会被纪录在被呼叫函式的local system table里的。因此,参数被传入时是 <i>以其值传入的(call by value)</i> 。在此的值指的是物件的参考( <i>reference</i> ),而非物件本身的 <i>值</i>。 <a name="tex2html2" href="#foot1251"><sup>4.1</sup></a> 当一个函式呼叫另一个函式时,就会因此呼叫而建立一个新的local system table。 </p> <p> 当定义函式的时候,也就在目前所在的system table里定义了这个函式的名称。对直译器来说,这个函式名称的资料型态是一个使用者自订的函式。这个函式的值名称可以被设定给另一个名称,然后这个新的名称就可以被当作是一个函式名称来使用。这个过程就是一个一般的重新命名的机制。 </p> <p> </p> <dl> <dd><pre class="verbatim">>>> fib<br><function object at 10042ed0><br>>>> f = fib<br>>>> f(100)<br>1 1 2 3 5 8 13 21 34 55 89<br></pre> </dd> </dl> <p> 你也许认为 <code>fib</code> 不是一个函式(function)而是一个程序(procedure)。如同在C中一样,在Python的procedure指的是没有传回值的函式(function)。事实上,就技术上而言,procedure也是有传回值的,只是所传回的是一个Python系统内键的值,叫做 <code>None</code> 。通常来说,如果只传回 <code>None</code> 的话,直译器不会印出这一个传回值。但是,如果你真想看一看它的话,你可以这样做: </p> <p> </p> <dl> <dd><pre class="verbatim">>>> print fib(0)<br>None<br></pre> </dd> </dl> <p> 如果想让你的函式传回一个包含费氏数列的list,而不是只印出来的话,其实是很简单的: </p> <p> </p> <dl> <dd><pre class="verbatim">>>> def fib2(n): # return Fibonacci series up to n<br>... "Return a list containing the Fibonacci series up to n"<br>... result = []<br>... a, b = 0, 1<br>... while b < n:<br>... result.append(b) # see below<br>... a, b = b, a+b<br>... return result<br>... <br>>>> f100 = fib2(100) # call it<br>>>> f100 # write the result<br>[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]<br></pre> </dd> </dl> <p> 如同往例,这个例子事实上示范了一些新的Python的特点: </p> <p> </p> <ul> <li><tt class="keyword">return</tt> 叙述使得函式传回了一个值。如果单单 <tt class="keyword">return</tt> 没有其他的expression来表示传回的值时,就表示这是一个从procedure传回来的写法(procedure到结束都没有传回值也是表示从procedure传回来)。这种写法表示传回值是 <code>None</code> 。 <p> </p> </li> <li><code>result.append(b)</code> 这个叙述表示呼叫了 <code>result</code> 这个list物件的一个方法( <i>method</i> ) 。Method是一个特别”属于”某个物件的函式,而且其名称的形式是 <code>obj.methodname</code> 。在这里 <code>obj</code> 指的是某一个物件(我们也可以用expression来代替),而 <code>methodname</code> 指得是由这个物件的资料型态所定义的这个方法的名称。不同的资料型态会定义不同的方法,不同的资料型态也许所定义的方法名称会相同,但是并不会造成冲突(你可以定义你自己的资料型态及其方法,我们称之为类别( <i>classes</i> ),后面会再谈到的)。在这个例子里的 <tt class="method">append()</tt> 方法是在list这个资料型态中定义的。这个方法会在list的最后面加入一个新的成员,在这个例子里也可以写作 "<tt class="samp">result = result + [b]</tt>" ,效果一样,但是用方法来写有效率多了。 <p> </p> </li> </ul> <p> </p> <h1> <br> 4.7 定义函式(续) </h1> <p> 在定义函式的时候我们可以加入不定数目的参数,加入参数的写法有三种,是可以混和使用的。 </p> <p> </p> <h2> <br> 4.7.1 预设内定参数值 </h2> <p> 最好用的一种写法是,对其中的一个或多个参数给它一个特定的预设值。这样子的话,当你在呼叫函式时,就可以不用传入参数,或是传入较少的参数了。请看下例: </p> <p> </p> <dl> <dd><pre class="verbatim">def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):<br> while 1:<br> ok = raw_input(prompt)<br> if ok in ('y', 'ye', 'yes'): return 1<br> if ok in ('n', 'no', 'nop', 'nope'): return 0<br> retries = retries - 1<br> if retries < 0: raise IOError, 'refusenik user'<br> print complaint<br></pre> </dd> </dl> <p> 当你呼叫这个函式的时候你可以用 <code>ask_ok('Do you reallywant to quit?')</code> ,或者是 <code>ask_ok('OK to overwrite the file?', 2)</code> 。 </p> <p> 设定的预设值可以是一个变数,但是这个变数在函式定义的时候就以定义时的情况( <i>defining</i> scope )决定(evaluate)了其值,所以以下的例子: </p> <p> </p> <dl> <dd><pre class="verbatim">i = 5<br>def f(arg = i): print arg<br>i = 6<br>f()<br></pre> </dd> </dl> <p> 印出的结果会是 <code>5</code> 。 </p> <p> <b>重要的警告:</b> 这个参数预设值只有被evaluate一次,这在当预设值是可变的物件像是list或是dictionary时会造成重要的差别。举例来说,底下的函式会记录曾经被呼叫过每次所传入的参数。 </p> <p> </p> <dl> <dd><pre class="verbatim">def f(a, l = []):<br> l.append(a)<br> return l<br>print f(1)<br>print f(2)<br>print f(3)<br></pre> </dd> </dl> <p> 印出来的结果会是: </p> <p> </p> <dl> <dd><pre class="verbatim">[1]<br>[1, 2]<br>[1, 2, 3]<br></pre> </dd> </dl> <p> 所以如果你的预设值是一个可变的物件,但是你又不想让每次呼叫都共用的时候,你就必须如此写你的函式: </p> <p> </p> <dl> <dd><pre class="verbatim">def f(a, l = None):<br> if l is None:<br> l = []<br> l.append(a)<br> return l<br></pre> </dd>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -