教程:使用Python和Sage进行编程

本教程是对使用Python和Sage进行基本编程的介绍,面向对编程有基本概念但不熟悉Python语言的读者。这远远不是详尽的。有关更完整的教程,请参阅 Python Tutorial 。也是 Python 的 documentation 尤其是 standard library 可能会很有用。

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

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

数据结构

在Python语言中, typing is dynamic ;没有声明变量这回事。该功能 type() 返回对象的类型 obj 。将对象转换为类型的步骤 typ 只要写信就行了 typ(obj) 如中所示 int("123") 。该命令 isinstance(ex, typ) 返回该表达式是否 ex 是一种 typ 。具体地说,任何值都是 an instance of a class 并且类和类型之间没有区别。

这个符号 = 表示对变量的影响;不应与 == 这表示数学上的等式。不平等是 !=

这个 standard typesboolintlisttuplesetdictstr

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

  • Python类型 int 用于表示大小有限的整数。为了使用精确算术处理任意大整数,Sage使用自己的名为 Integer

  • A list 是对值进行分组的数据结构。它是使用方括号构建的,如 [1, 3, 4] 。这个 range() 函数创建整数列表。用户还可以使用以下命令创建列表 list comprehension

    [ <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 非常类似于列表;它是使用圆括号构建的。空元组通过以下方式获得 () 或由构造函数 tuple 。如果只有一个元素,则必须写 (a,) 。元组是 immutable (一个人不能改变它)但它是 hashable (见下文)。还可以使用理解来创建元组::

    sage: tuple(i^2 for i in range(10) if i % 2 == 0)
    (0, 4, 16, 36, 64)
    
  • A set 是一种数据结构,它包含没有重数或顺序的值。您可以使用构造函数从列表(或任何可迭代的)创建它 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 dictionary 是一个关联表,它将值与键相关联。密钥必须是可散列的。一种是使用构造函数创建词典 dict ,或使用以下语法:

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

    例如::

    sage: age = {'toto' : 8, 'mom' : 27}; age
    {'mom': 27, 'toto': 8}
    
  • 引号(简单 ' ' 或双倍 " " )随函附上 character strings 。可以使用以下命令将它们连接起来 +

  • 对于列表、元组、字符串和词典, indexing operator 是这样写的 l[i] 。对于列表、元组和字符串,也可以使用 slices AS l[:]l[:b]l[a:] ,或 l[a:b] 。负指数从末尾开始。

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

  • 最后,有一个特殊的值,称为 None 表示没有值。

控制结构

在Python中,指令块的开始和结束没有关键字。块仅通过缩进的方式来定界。大多数情况下,新块是由 : 。Python具有以下控制结构:

  • 条件指令:

    if <condition>:
        <instruction sequence>
    [elif <condition>:
        <instruction sequence>]*
    [else:
        <instruction sequence>]
    
  • 在Exposal Exposal中,可以这样写:

    <value> if <condition> else <value>
    
  • 迭代说明:

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

    这个 else 如果循环正常结束,即既不是由 break 也不例外。

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

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

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

    raise <ErrorType>[("error message")]
    

    常见错误包括 ValueErrorTypeError

功能

备注

Python函数与数学函数

在下面的内容中,我们将处理 functions 是一种 programming languages 。在微积分中操作的数学函数,由Sage以不同的方式处理。特别是,对Python函数进行加法或派生等数学操作是没有意义的。

一种使用关键字定义函数 def 作为:

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

该函数的结果由指令给出 return 。可以使用以下命令匿名创建非常短的函数 lambda (请注意,没有说明 return 在此):

lambda <arguments>: <expression>

备注

函数式编程

与任何其他对象一样,函数也是对象。可以将它们赋给变量或返回它们。有关详细信息,请参阅 面向数学家的函数式编程

习题

列表

创建列表I: [Square brackets]

Example:

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]

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

sage: # edit here

Exercise: 创建空列表(您经常需要这样做)。

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.

Exercise: 使用 range() 构建列表的步骤 [1,2,ldots,50]

sage: # edit here

Exercise: 使用 range() 构建……的列表 even 介于1和100(包括100)之间的数字。

sage: # edit here

Exercise: 这个 step 的论据 range() 命令可以是负的。使用Range构造列表 [10, 7, 4, 1, -2]

sage: # edit here

参见

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

  • srange() :Like Range,但带有Sage整数;见下文。

  • xsrange() :类似于xrange,但带有Sage整数。

创建列表III:列表理解

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

Example 我们已经知道如何创建列表 [1, 2, dots, 16] **

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

使用 list comprehension ,我们现在可以创建列表了 [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\]

求出前100个自然数的平方和与总和的平方之间的差值。

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

列表可以是 filtered 使用列表理解。

Example: 为了创建介于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]

Exercise: 使用 list comprehension 列出20以下是3或5的倍数的所有自然数。提示:

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

  • 要测试是否相等,请使用两个等号 (== );例如, 3 == 7

sage: # edit here

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

sage: # edit here
嵌套列表理解

列表理解可以嵌套!

Examples:

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]

Exercise:

  1. A Pythagorean triple 是一个三元组 (x,y,z)positive 满足条件的整数 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 是项的索引。

Exercise:

  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]

修改列表:追加和扩展

append 列表中的对象::

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

extend 由另一个列表列出的列表::

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

Exercise: 下面是一些切片列表的例子。在计算单元格之前,尝试猜测输出是什么::

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]

Exercise (Advanced): 下面的函数将循环与上面的一些列表操作结合在一起。该函数的作用是什么?

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 tuple 是一种 immutable 单子。也就是说,一旦创建,它就不能更改。这对于代码安全非常有用,最重要的是它创建了元组 hashable 。要创建元组,请使用圆括号而不是方括号::

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

要创建一个Singleton元组,需要使用逗号来解决歧义:

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]
[]

一个很好的“ Python ”技巧是使用生成器作为函数的参数。我们有 not 此命令需要使用双圆括号::

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

辞典

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

有几种定义词典的方法。一种方法是使用大括号, {} ,并以逗号分隔的形式给出条目 key:value **

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元组的列表(或者实际上是任何可迭代的) (key, value) **

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 ,或 values ,或者两者兼而有之。请注意,在内部,不会对键进行排序。通常,键/值的顺序将取决于不同计算机和/或同一计算机上的重复运行的存储位置可以且将会不同。但是,Sage在打印词典时会按键对词典条目进行排序,以使文档字符串更具重现性。但是,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')]

Exercise: 考虑下面的有向图。

_images/graph0.png

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

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

然后尝试:

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

使用Sage类型:srange命令

Example: 构建一个 3 times 3 其矩阵 (i,j) 表项是有理数 frac{i}{j} 。由生成的整数 range() 是 Python 吗? int 因此,将它们相除会得到欧几里得除法(在Python2中):

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整数的除法返回一个浮点数。

而分裂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]]

这就是众所周知的 reference effect 。您可以使用命令 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

While 环圈

While 循环的使用率往往不如 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

中的子句表达式的真值 while 使用以下命令计算循环 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: list(range(4))
[0, 1, 2, 3]
sage: list(range(1, 5))
[1, 2, 3, 4]
sage: list(range(1, 11, 2))
[1, 3, 5, 7, 9]
sage: list(range(10, 0, -1))
[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

您可以使用 continue 关键字立即转到循环中的下一项::

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

如果您想要跳出循环,请使用 break 关键词::

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__??

该命令 yield 提供了一种非常方便的方法来生成迭代器。我们稍后会看到更多关于它的信息。

习题

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

  1. 第一 n 调和级数的术语:

    \[\sum_{i=1}^n\frac{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 既不能被整除也不能被整除的正整数 2 也不会被 3 也不会被 5 **

    sage: # edit here
    

功能

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

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}

让我们使用 yield 关于制作斐波纳契数生成器的说明 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 -第几个斐波纳契数。努力提高性能。