教程:用Python和Sage编程

本教程将介绍Python和Sage中的基本编程,读者将了解编程的基本概念,但不熟悉Python语言。它远不是详尽无遗的。有关更完整的教程,请查看 Python Tutorial . 也是Python的 documentation 尤其是 standard library 可能有用。

A more advanced tutorial 介绍Python中对象和类的概念。

下面是学习Python的更多资源:

数据结构

在 Python 中, 打字是动态的 不存在声明变量的事情。功能 type() 返回对象的类型 obj . 将对象转换为类型 typ 就写吧 typ(obj) 如在 int("123") . 命令 isinstance(ex, typ) 返回表达式是否 ex 属于类型 typ . 具体来说,任何值都是 类的实例 类和类型之间没有区别。

符号 = 表示对变量的矫饰;不应与 == 表示数学上的相等。不平等是 != .

这个 标准类型boolintlisttuplesetdictstr .

  • 类型 bool布尔运算 )有两个值: TrueFalse . 布尔运算符由它们的名称表示 orandnot .

  • Python类型 intlong 用于表示有限大小的整数。Sage使用自己的类型名为 Integer .

  • A list 是对值进行分组的数据结构。它是使用括号构造的,如中所示 [1, 3, 4] . 这个 range() 函数创建整数列表。也可以使用 列表理解

    [ <expr> for <name> in <iterable> (if <condition>) ]
    

    例如::

    sage: [ i^2 for i in range(10) if i % 2 == 0 ]
    [0, 4, 16, 36, 64]
    
  • A 元组 非常类似于列表;它是用括号构造的。空元组通过 () 或由建造师 tuple . 如果只有一个元素,就必须写 (a,) . 元组是 不变的 (一个人无法改变它)但是它是 可装卸的 (见下文)。也可以使用理解来创建元组:

    sage: tuple(i^2 for i in range(10) if i % 2 == 0)
    (0, 4, 16, 36, 64)
    
  • A set 是一种数据结构,它包含没有重数或顺序的值。可以使用构造函数从列表(或任何iterable)中创建它 set . 集合的元素必须是散列的:

    sage: set([2,2,1,4,5])
    {1, 2, 4, 5}
    
    sage: set([ [1], [2] ])
    Traceback (most recent call last):
    ...
    TypeError: unhashable type: 'list'
    
  • A 词典 是一个关联表,它将值与键相关联。密钥必须是散列的。使用构造函数创建字典 dict ,或使用以下语法:

    {key1 : value1, key2 : value2 ...}
    

    例如::

    sage: age = {'toto' : 8, 'mom' : 27}; age
    {'mom': 27, 'toto': 8}
    
  • 引号(简单 ' ' 或者双倍 " " )封闭 字符串 . 可以使用 + .

  • 对于列表、元组、字符串和字典 索引运算符 是书面的 l[i] . 对于列表、元组和字符串,也可以使用 作为 l[:]l[:b]l[a:]l[a:b] . 负指数从末尾开始。

  • 这个 len() 函数返回列表、元组、集、字符串或字典的元素数。有人写道 x in C 测试 x 是在 C .

  • 最后还有一个特殊的值叫做 None 表示没有值。

控制结构

在Python中,指令块的开头和结尾没有关键字。块仅通过缩进来分隔。在大多数情况下,新块是由 : . Python具有以下控制结构:

  • 条件指令:

    if <condition>:
        <instruction sequence>
    [elif <condition>:
        <instruction sequence>]*
    [else:
        <instruction sequence>]
    
  • 在表达式内部,可以写下:

    <value> if <condition> else <value>
    
  • 迭代指令:

    for <name> in <iterable>:
        <instruction sequence>
    [else:
        <instruction sequence>]
    
    while <condition>:
        <instruction sequence>
    [else:
        <instruction sequence>]
    

    这个 else 块在循环结束时执行,如果循环正常结束,则 break 也不例外。

  • 在一个循环中, continue 跳到下一个迭代。

  • iterable是一个可以迭代的对象。Iterable类型包括列表、元组、字典和字符串。

  • 错误(也称为异常)由以下原因引发:

    raise <ErrorType> [, error message]
    

    常见错误包括 ValueErrorTypeError .

功能

注解

Python函数与数学函数

在接下来的内容中,我们处理 功能 是什么意思 程序设计语言 . 在微积分中,数学函数是由Sage以不同的方式处理的。尤其是在Python函数上进行数学操作(如添加或派生)是没有意义的。

使用关键字定义函数 def AS:

def <name>(<argument list>):
     <instruction sequence>

函数的结果由指令给出 return . 可以使用匿名方式创建非常短的函数 lambda (注意没有指示 return 在这里):

lambda <arguments>: <expression>

注解

函数式编程

函数和其他对象一样是对象。可以将它们分配给变量或返回它们。有关详细信息,请参见上的教程 数学家函数编程 .

练习

列表

创建列表I: [方括号]

例子:

sage: L = [3, Permutation([5,1,4,2,3]), 17, 17, 3, 51]
sage: L
[3, [5, 1, 4, 2, 3], 17, 17, 3, 51]

练习: 创建列表 [63, 12, -10, "a", 12] ,将其分配给变量 L ,并打印列表。

sage: # edit here

练习: 创建空列表(通常需要这样做)。

sage: # edit here

创建列表II:范围

这个 range() 函数提供了构造整数列表的简单方法。以下是 range() 功能:

range([start,] stop[, step]) -> list of integers

Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement). For
example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
These are exactly the valid indices for a list of 4 elements.

练习: 使用 range() 构建列表 [1,2,ldots,50] .

sage: # edit here

练习: 使用 range() 构建 even 1到100之间的数字(包括100)。

sage: # edit here

练习: 这个 step 的参数 range() 命令可以是负数。使用范围构造列表 [10, 7, 4, 1, -2] .

sage: # edit here

参见

  • xrange() :返回迭代器而不是构建列表(仅适用于Python2,在python3中被range替换)。

  • srange() :与范围相似,但带有Sage整数;见下文。

  • xsrange() :与xrange相似,但带有Sage整数。

创建列表III:列表理解

列表解析 提供从其他列表(或其他数据类型)创建列表的简明方法。

例子 我们已经知道如何创建列表 [1, 2, dots, 16] ::

sage: range(1,17)   # py2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

使用A 列表理解 ,我们现在可以创建列表 [1^2, 2^2, 3^2, dots, 16^2] 如下:

sage: [i^2 for i in range(1,17)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256]
sage: sum([i^2 for i in range(1,17)])
1496

Exercise: [Project Euler, Problem 6]

前十个自然数的平方和为

\[(1^2+2^2+。。。+10^2)=385\]

前十个自然数之和的平方是

\[(1+2+。。。+10)^2=55^2=3025\]

因此,前十个自然数的平方和和与之和的平方之差为

\[3025-385=2640\]

找出前一百个自然数的平方和和和的平方的差。

sage: # edit here
sage: # edit here
sage: # edit here
使用列表理解过滤列表

列表可以是 过滤的 使用列表理解。

例子: 要创建1到100之间的素数平方的列表,我们使用如下列表理解。

sage: [p^2 for p in [1,2,..,100] if is_prime(p)]
[4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681, 1849, 2209, 2809, 3481, 3721, 4489, 5041, 5329, 6241, 6889, 7921, 9409]

练习: 使用A 列表理解 列出20以下所有3或5的倍数的自然数。提示:

  • 要得到7除以3的余数,请使用 7%3 .

  • 用两个等号来检验相等性 (== );例如, 3 == 7 .

sage: # edit here

Project Euler, Problem 1: 求1000以下所有3或5的倍数之和。

sage: # edit here
嵌套列表理解

列表理解可以嵌套!

例子:

sage: [(x,y) for x in range(5) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2)]
sage: [[i^j for j in range(1,4)] for i in range(6)]
[[0, 0, 0], [1, 1, 1], [2, 4, 8], [3, 9, 27], [4, 16, 64], [5, 25, 125]]
sage: matrix([[i^j for j in range(1,4)] for i in range(6)])
[  0   0   0]
[  1   1   1]
[  2   4   8]
[  3   9  27]
[  4  16  64]
[  5  25 125]

练习:

  1. A 三重勾股 是三倍的 (x,y,z) 属于 积极的 满足整数 x^2+y^2=z^2 . 毕达哥拉斯的三元组,其组分最多 10 是:

    \[[(3,4,5),(4,3,5),(6,8,10),(8,6,10)] ,.\]

    使用过滤的列表理解,构造一个包含最多个组件的毕达哥拉斯三元组的列表 50 ::

    sage: # edit here
    
    sage: # edit here
    
  2. Project Euler, Problem 9: 只有一个毕达哥拉斯式的三元组 a + b + c = 1000 . 找到产品 abc ::

    sage: # edit here
    

访问列表的单个元素

访问列表中的元素 L ,使用语法 L[i] 在哪里 i 是项的索引。

练习:

  1. 构建列表 L = [1,2,3,4,3,5,6] . 是什么 L[3] 是吗?

    sage: # edit here
    
  2. 是什么 L[1] 是吗?

    sage: # edit here
    
  3. 的第一个元素的索引是什么 L 是吗?

    sage: # edit here
    
  4. 是什么 L[-1] ? 是什么 L[-2] 是吗?

    sage: # edit here
    
  5. 是什么 L.index(2) ? 是什么 L.index(3) 是吗?

    sage: # edit here
    

修改列表:更改列表中的元素

更改项目位置 i 列表的 L ::

sage: L = ["a", 4, 1, 8]
sage: L
['a', 4, 1, 8]
sage: L[2] = 0
sage: L
['a', 4, 0, 8]

修改列表:附加和扩展

追加 列表的对象:

sage: L = ["a", 4, 1, 8]
sage: L
['a', 4, 1, 8]
sage: L.append(17)
sage: L
['a', 4, 1, 8, 17]

延伸 另一个列表的列表:

sage: L1 = [1,2,3]
sage: L2 = [7,8,9,0]
sage: L1
[1, 2, 3]
sage: L2
[7, 8, 9, 0]
sage: L1.extend(L2)
sage: L1
[1, 2, 3, 7, 8, 9, 0]

修改列表:反转、排序。。。

sage: L = [4,2,5,1,3]
sage: L
[4, 2, 5, 1, 3]
sage: L.reverse()
sage: L
[3, 1, 5, 2, 4]
sage: L.sort()
sage: L
[1, 2, 3, 4, 5]
sage: L = [3,1,6,4]
sage: sorted(L)
[1, 3, 4, 6]
sage: L
[3, 1, 6, 4]

连接列表

若要连接两个列表,请使用运算符将它们相加 + . 这不是交换操作!

sage: L1 = [1,2,3]
sage: L2 = [7,8,9,0]
sage: L1 + L2
[1, 2, 3, 7, 8, 9, 0]

切片列表

可以使用以下语法对列表进行切片 L[start : stop : step] . 这将返回 L .

练习: 下面是一些切片列表的示例。在计算单元格之前,请尝试猜测输出结果:

sage: L = list(range(20))
sage: L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
sage: L[3:15]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
sage: L[3:15:2]
[3, 5, 7, 9, 11, 13]
sage: L[15:3:-1]
[15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4]
sage: L[:4]
[0, 1, 2, 3]
sage: L[:]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
sage: L[::-1]
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

练习(高级): 下面的函数将循环与上面的一些列表操作组合在一起。函数的作用是什么?

sage: def f(number_of_iterations):
....:     L = [1]
....:     for n in range(2, number_of_iterations):
....:         L = [sum(L[:i]) for i in range(n-1, -1, -1)]
....:     return numerical_approx(2*L[0]*len(L)/sum(L), digits=50)
sage: # edit here

多元组

A 元组 是一个 不变的 列表。也就是说,它一旦创建就不能更改。这对于代码安全非常有用,最重要的原因是它生成元组 可装卸的 . 要创建元组,请使用括号而不是括号::

sage: t = (3, 5, [3,1], (17,[2,3],17), 4)
sage: t
(3, 5, [3, 1], (17, [2, 3], 17), 4)

要创建单例元组,需要使用逗号来解决歧义:

sage: (1)
1
sage: (1,)
(1,)

我们可以从列表创建元组,反之亦然。

sage: tuple(range(5))
(0, 1, 2, 3, 4)
sage: list(t)
[3, 5, [3, 1], (17, [2, 3], 17), 4]

元组在许多方面类似于列表:

操作

列表的语法

元组的语法

查阅信件

list[3]

tuple[3]

级联

list1 + list2

tuple1 + tuple2

切片

list[3:17:2]

tuple[3:17:2]

颠倒的副本

list[::-1]

tuple[::-1]

长度

len(list)

len(tuple)

尝试修改元组将失败::

sage: t = (5, 'a', 6/5)
sage: t
(5, 'a', 6/5)
sage: t[1] = 'b'
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment

生成器

“元组理解”并不存在。相反,语法生成了一个称为生成器的东西。生成器允许您一次处理一个项目序列。每一项都是在需要时创建的,然后被遗忘。如果我们只需要使用每件物品一次,这会非常有效。

sage: (i^2 for i in range(5))
<generator object <genexpr> at 0x...>
sage: g = (i^2 for i in range(5))
sage: g[0]
Traceback (most recent call last):
...
TypeError: 'generator' object ...
sage: [x for x in g]
[0, 1, 4, 9, 16]

g 现在是空的。

sage: [x for x in g]
[]

一个不错的“pythonic”技巧是使用生成器作为函数的参数。我们有 not 需要双括号:

sage: sum( i^2 for i in srange(100001) )
333338333350000

辞典

A 词典 是另一种内置数据类型。与列表不同,列表是按从0开始的一系列数字编制索引的,字典的索引依据 keys ,可以是任何不可变的对象。字符串和数字总是可以是键(因为它们是不可变的)。字典有时在其他编程语言中被称为“关联数组”。

定义字典有几种方法。一种方法是用大括号, {{}} ,表格中给出了逗号分隔的条目 键:值 ::

sage: d = {3:17, 0.5:[4,1,5,2,3], 0:"goo", 3/2 : 17}
sage: d
{0: 'goo', 0.500000000000000: [4, 1, 5, 2, 3], 3/2: 17, 3: 17}

第二种方法是使用构造函数 dict 它允许一个2元组的列表(或者实际上是任何iterable) 值(键) ::

sage: dd = dict((i,i^2) for i in range(10))
sage: dd
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

对于一些重要的字典和操作,元组和操作都是重要的。

操作

列表的语法

词典语法

访问元素

list[3]

D["key"]

长度

len(list)

len(D)

修改

L[3] = 17

D["key"] = 17

删除项目

del L[3]

del D["key"]

sage: d[10]='a'
sage: d
{0: 'goo', 0.500000000000000: [4, 1, 5, 2, 3], 3/2: 17, 3: 17, 10: 'a'}

一个字典可以多次具有相同的值,但每个键只能出现一次并且必须是不可变的:

sage: d = {3: 14, 4: 14}
sage: d
{3: 14, 4: 14}
sage: d = {3: 13, 3: 14}
sage: d
{3: 14}
sage: d = {[1,2,3] : 12}
Traceback (most recent call last):
...
TypeError: unhashable type: 'list'

另一种向字典中添加项目的方法是使用 update() 从另一个词典更新词典的方法::

sage: d = {}
sage: d
{}
sage: d.update({10 : 'newvalue', 20: 'newervalue', 3: 14, 0.5:[1,2,3]})
sage: d
{0.500000000000000: [1, 2, 3], 3: 14, 10: 'newvalue', 20: 'newervalue'}

我们可以迭代 keys价值观 或两者兼而有之。注意,在内部,没有对键进行排序。一般来说,键/值的顺序取决于不同计算机和/或在同一台计算机上重复运行的内存位置的不同。但是,Sage在打印字典时按键对字典条目进行排序,以使docstring更具可复制性。但是,Python方法 keys()values() 不要为你分类。如果你想要你的输出是可复制的,那么你必须像下面的例子一样先对它排序:

sage: d = {10 : 'newvalue', 20: 'newervalue', 3: 14, 0.5:(1,2,3)}
sage: sorted([key for key in d])
[0.500000000000000, 3, 10, 20]
sage: d.keys()   # random order
[0.500000000000000, 10, 3, 20]
sage: sorted(d.keys())
[0.500000000000000, 3, 10, 20]
sage: d.values()   # random order
[(1, 2, 3), 'newvalue', 14, 'newervalue']
sage: set(d.values()) == set([14, (1, 2, 3), 'newvalue', 'newervalue'])
True
sage: d.items()    # random order
[(0.500000000000000, (1, 2, 3)), (10, 'newvalue'), (3, 14), (20, 'newervalue')]
sage: sorted([(key, value) for key, value in d.items()])
[(0.500000000000000, (1, 2, 3)), (3, 14), (10, 'newvalue'), (20, 'newervalue')]

练习: 考虑下面的有向图。

thematic_tutorials/media/graph0.png

创建一个字典,其键是上述有向图的顶点,其值是它指向的顶点列表。例如,顶点1指向顶点2和3,因此字典将如下所示:

d = { ..., 1:[2,3], ... }
sage: # edit here

然后尝试:

sage: g = DiGraph(d)
sage: g.plot()

使用Sage类型:srange命令

例子: 构建一个 3 times 3 谁的矩阵 (i,j) 入口是有理数 frac{{i}}{{j}} . 由生成的整数 range() 是 Python 吗 int 因此,对它们进行欧几里德除法(在 Python 2中)::

sage: matrix([[i/j for j in range(1,4)] for i in range(1,4)]) # not tested
[1 0 0]
[2 1 0]
[3 1 1]

在Python3中,Python整数的除法返回一个float。

而将Sage分开 Integer 一位Sage Integer 产生一个有理数:

sage: matrix([[ i/j for j in srange(1,4)] for i in srange(1,4)])
[  1 1/2 1/3]
[  2   1 2/3]
[  3 3/2   1]

修改列表会有后果!

尝试预测以下命令的结果:

sage: a = [1, 2, 3]
sage: L = [a, a, a]
sage: L
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
sage: a.append(4)
sage: L
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]

现在试试这些:

sage: a = [1, 2, 3]
sage: L = [a, a, a]
sage: L
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
sage: a = [1, 2, 3, 4]
sage: L
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
sage: L[0].append(4)
sage: L
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]

这被称为 参考效应 . 您可以使用命令 deepcopy() 为了避免这种影响:

sage: a = [1,2,3]
sage: L = [deepcopy(a), deepcopy(a)]
sage: L
[[1, 2, 3], [1, 2, 3]]
sage: a.append(4)
sage: L
[[1, 2, 3], [1, 2, 3]]

字典也有同样的效果:

sage: d = {1:'a', 2:'b', 3:'c'}
sage: dd = d
sage: d.update( { 4:'d' } )
sage: dd
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}

循环和函数

对于这里所发生的事情的更详细的解释,下面是Python教程的一个好地方:http://docs.python.org/tutorial/controlflow.html

同时 循环

同时 循环的使用量往往不如 for Python代码中的循环:

sage: i = 0
sage: while i < 10:
....:     print(i)
....:     i += 1
0
1
2
3
4
5
6
7
8
9
sage: i = 0
sage: while i < 10:
....:     if i % 2 == 1:
....:         i += 1
....:         continue
....:     print(i)
....:     i += 1
0
2
4
6
8

注意,中子句表达式的真值 虽然 循环使用 bool ::

sage: bool(True)
True
sage: bool('a')
True
sage: bool(1)
True
sage: bool(0)
False
sage: i = 4
sage: while i:
....:     print(i)
....:     i -= 1
4
3
2
1

For 循环

这是一个基本的 for 循环遍历列表中的所有元素 l ::

sage: l = ['a', 'b', 'c']
sage: for letter in l:
....:     print(letter)
a
b
c

这个 range() 当您想要生成要循环的算术级数时,函数非常有用。请注意,不包括终点:

sage: range?
sage: range(4)  # py2
[0, 1, 2, 3]
sage: range(1, 5)  # py2
[1, 2, 3, 4]
sage: range(1, 11, 2)  # py2
[1, 3, 5, 7, 9]
sage: range(10, 0, -1)  # py2
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
sage: for i in range(4):
....:     print("{} {}".format(i, i*i))
0 0
1 1
2 4
3 9

你可以使用 持续 关键字以立即转到循环中的下一项:

sage: for i in range(10):
....:     if i % 2 == 0:
....:         continue
....:     print(i)
1
3
5
7
9

如果要跳出循环,请使用 打破 关键词:

sage: for i in range(10):
....:     if i % 2 == 0:
....:         continue
....:     if i == 7:
....:         break
....:     print(i)
1
3
5

如果您需要同时跟踪列表中的位置及其值,一种(不那么优雅)的方法是执行以下操作:

sage: l = ['a', 'b', 'c']
sage: for i in range(len(l)):
....:     print("{} {}".format(i, l[i]))
0 a
1 b
2 c

用起来更干净 enumerate() 它提供了索引和值:

sage: l = ['a', 'b', 'c']
sage: for i, letter in enumerate(l):
....:     print("{} {}".format(i, letter))
0 a
1 b
2 c

你可以得到与 enumerate() 使用函数 zip() 要将两个列表压缩在一起:

sage: l = ['a', 'b', 'c']
sage: for i, letter in zip(range(len(l)), l):
....:     print("{} {}".format(i, letter))
0 a
1 b
2 c

For 循环使用Python的迭代器协议工作。这允许各种不同的对象循环。例如::

sage: for i in GF(5):
....:     print("{} {}".format(i, i*i))
0 0
1 1
2 4
3 4
4 1

这是怎么回事?

sage: it = iter(GF(5)); it
<generator object ...__iter__ at 0x...>

sage: next(it)
0

sage: next(it)
1

sage: next(it)
2

sage: next(it)
3

sage: next(it)
4

sage: next(it)
Traceback (most recent call last):
...
StopIteration
sage: R = GF(5)
sage: R.__iter__??

命令 产量 提供了生成迭代器的非常方便的方法。我们稍后再看。

练习

对于以下每个集合,计算其元素的列表及其总和。如果可能的话,使用两种不同的方法:使用循环和使用列表理解。

  1. 第一 n 谐波级数项:

    \[和{i=1}^nfrac{1}{i}\]
    sage: # edit here
    
  2. 之间的奇数 1n ::

    sage: # edit here
    
  3. 第一 n 奇数:

    sage: # edit here
    
  4. 之间的整数 1n 既不能被整除的 2 也不是 3 也不是 5 ::

    sage: # edit here
    
  5. 第一 n 整数介于 1n 既不能被整除的 2 也不是 3 也不是 5 ::

    sage: # edit here
    

功能

函数是使用 def 语句,并使用 返回 关键词:

sage: def f(x):
....:     return x*x
sage: f(2)
4

函数可以是递归的:

sage: def fib(n):
....:     if n <= 1:
....:         return 1
....:     else:
....:         return fib(n-1) + fib(n-2)
sage: [fib(i) for i in range(10)]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

函数和其他对象一样是一类对象。例如,它们可以作为参数传递给其他函数:

sage: f
<function f at 0x...>
sage: def compose(f, x, n):   # computes f(f(...f(x)))
....:     for i in range(n):
....:         x = f(x)        # this change is local to this function call!
....:     return x
sage: compose(f, 2, 3)
256
sage: def add_one(x):
....:     return x + 1
sage: compose(add_one, 2, 3)
5

可以为函数中的参数指定默认值:

sage: def add_n(x, n=1):
....:     return x + n
sage: add_n(4)
5
sage: add_n(4, n=100)
104
sage: add_n(4, 1000)
1004

可以从函数中返回多个值::

sage: def g(x):
....:     return x, x*x
sage: g(2)
(2, 4)
sage: type(g)
<... 'function'>
sage: a,b = g(100)
sage: a
100
sage: b
10000

您还可以在函数中获取可变数量的参数和关键字参数::

sage: def h(*args, **kwds):
....:     print("{} {}".format(type(args), args))
....:     print("{} {}".format(type(kwds), kwds))
sage: h(1,2,3,n=4)
<... 'tuple'> (1, 2, 3)
<... 'dict'> {'n': 4}

让我们使用 产量 指令为Fibonacci数到 n ::

sage: def fib_gen(n):
....:     if n < 1:
....:         return
....:     a = b = 1
....:     yield b
....:     while b < n:
....:         yield b
....:         a, b = b, b+a
sage: for i in fib_gen(50):
....:     print(i)
1
1
2
3
5
8
13
21
34

练习

  1. 编写函数 is_even 哪些回报 True 如果 n 是偶数和 False 否则。

  2. 编写函数 every_other 需要一张单子 l 作为输入,并返回一个包含 l .

  3. 编写生成器 every_other 这需要一个巨大的 l 作为输入,并返回 l ,一个接一个。

  4. 编写一个函数来计算 n -斐波纳契数。努力提高表现。