4.7 定义函数(下)

【原文】

The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables and variables of enclosing functions cannot be directly assigned a value within a function (unless, for global variables, named in a global statement, or, for variables of enclosing functions, named in a nonlocal statement), although they may be referenced.

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). 1 When a function calls another function, or calls itself recursively, a new local symbol table is created for that call.

A function definition associates the function name with the function object in the current symbol table. The interpreter recognizes the object pointed to by that name as a user-defined function. Other names can also point to that same function object and can also be used to access the function:

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

Coming from other languages, you might object that fib is not a function but a procedure since it doesn’t return a value. In fact, even functions without a return statement do return a value, albeit a rather boring one. This value is called None (it’s a built-in name). Writing the value None is normally suppressed by the interpreter if it would be the only value written. You can see it if you really want to using print():

>>> fib(0)
>>> print(fib(0))
None

It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of printing it:

>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

This example, as usual, demonstrates some new Python features:

  • The return statement returns with a value from a function. return without an expression argument returns None. Falling off the end of a function also returns None.

  • The statement result.append(a) calls a method of the list object result. A method is a function that ‘belongs’ to an object and is named obj.methodname, where obj is some object (this may be an expression), and methodname is the name of a method that is defined by the object’s type. Different types define different methods. Methods of different types may have the same name without causing ambiguity. (It is possible to define your own object types and methods, using classes, see Classes) The method append() shown in the example is defined for list objects; it adds a new element at the end of the list. In this example it is equivalent to result = result + [a], but more efficient.

4.8. More on Defining Functions

执行函数时使用的局部函数变量是一个新的符号表。更严谨些,一个函数中所有变量赋值后都将值存储在局部符号表;引用变量时先查看局部符号表,然后查看封闭函数的符号表,再是全局符号表,最后是内置名称表。因此,全局变量和封闭函数的变量可以被引用但不在调用函数中赋值(除非,用global语句命名全局变量。或者,用nonlocal语句命名封闭函数变量)。

函数调用的实际参数(参数)是函数局部符号表;因此,参数使用 call by value 传递(其中始终是对象引用 而不是对象的值)。当一个函数调用另一个函数,或者递归调用时,为调用创建一个新的局部符号表。

函数定义关联了函数对象的函数名,当前符号表。解释器通过函数名识别用户定义的函数。用函数名也可以指向相同的函数对象,访问该函数:

在其他语言,你认为fib对象不是一个函数而是一个过程,因为它不返回值。事实上,即使是没有return语句的函数也会返回一个值,尽管这是一个相当无聊的值。这个值就是None(它是一个内置名称)。如果None是唯一写入的值,通常解释器不显示None print()可以输出它。

相较输出一个菲波那切数列,编写一个斐波那契数列函数更简单:

此示例演示了一些Python的新功能:

  • return语句返回函数的值。return后没有表达式则返回None 。函数没有return在末尾自然结束也返回None
  • result.append(a)调用list对象append方法。方法是一个属于对象并被命名为obj.methodname的函数,其中,obj是某个对象(这可能是一个表达式), methodname是由对象类型定义的方法的名称。不同的对象类型定义不同的方法。不同对象类型的方法可能具有相同的名称而不会引起歧义。(使用可以定义自己的对象类型和方法,请参阅)。在示例中,append()是列表对象的方法,是为列表在末尾添加一个新元素。它等价于result = result + [a],但效率更高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值