# 编程¶

## 加载和附加Sage文件¶

print("Hello World")
print(2^3)


sage: load("example.sage")
Hello World
8


sage: attach("example.sage")
Hello World
8


print("Hello World")
print(Integer(2)**Integer(3))


（此准备在 sage/misc/interpreter.py

2 * 17 * 59


## 数据类型¶

Sage中的每个对象都有一个明确的类型。Python有许多基本的内置类型，Sage库还添加了更多的类型。一些内置的Python类型包括字符串、列表、元组、int和float，如图所示：

sage: s = "sage"; type(s)
<... 'str'>
sage: s = 'sage'; type(s)      # you can use either single or double quotes
<... 'str'>
sage: s = [1,2,3,4]; type(s)
<... 'list'>
sage: s = (1,2,3,4); type(s)
<... 'tuple'>
sage: s = int(2006); type(s)
<... 'int'>
sage: s = float(2006); type(s)
<... 'float'>


sage: V = VectorSpace(QQ, 1000000); V
Vector space of dimension 1000000 over Rational Field
sage: type(V)
<class 'sage.modules.free_module.FreeModule_ambient_field_with_category'>


sage: zeta = -1
sage: s=.5; s.zeta()
-1.46035450880959


sage: n = 2; n.sqrt()
sqrt(2)
sage: sqrt(2)
sqrt(2)
sage: V = VectorSpace(QQ,2)
sage: V.basis()
[
(1, 0),
(0, 1)
]
sage: basis(V)
[
(1, 0),
(0, 1)
]
sage: M = MatrixSpace(GF(7), 2); M
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7
sage: A = M([1,2,3,4]); A
[1 2]
[3 4]
sage: A.charpoly('x')
x^2 + 2*x + 5
sage: charpoly(A, 'x')
x^2 + 2*x + 5


## 列表、元组和序列¶

sage: v = [2, 3, 5, 'x', SymmetricGroup(3)]; v
[2, 3, 5, 'x', Symmetric group of order 3! as a permutation group]
sage: type(v)
<... 'list'>
sage: v[0]
2
sage: v[2]
5


（当索引到列表中时，如果索引不是Python int就可以了！）一个聪明的整数（或有理数，或任何带有 __index__ 方法）会很好地工作。

sage: v = [1,2,3]
sage: v[2]
3
sage: n = 2      # SAGE Integer
sage: v[n]       # Perfectly OK!
3
sage: v[int(n)]  # Also OK.
3


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


sage: L = [factor(n) for n in range(1, 15)]
sage: L
[1, 2, 3, 2^2, 5, 2 * 3, 7, 2^3, 3^2, 2 * 5, 11, 2^2 * 3, 13, 2 * 7]
sage: L[12]
13
sage: type(L[12])
<class 'sage.structure.factorization_integer.IntegerFactorization'>
sage: [factor(n) for n in range(1, 15) if is_odd(n)]
[1, 3, 5, 7, 3^2, 11, 13]


sage: L = [factor(n) for n in range(1, 20)]
sage: L[4:9]
[5, 2 * 3, 7, 2^3, 3^2]
sage: L[:4]
[1, 2, 3, 2^2]
sage: L[14:4]
[]
sage: L[14:]
[3 * 5, 2^4, 17, 2 * 3^2, 19]


sage: v = (1,2,3,4); v
(1, 2, 3, 4)
sage: type(v)
<... 'tuple'>
sage: v[1] = 5
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment


sage: v = Sequence([1,2,3,4/5])
sage: v
[1, 2, 3, 4/5]
sage: type(v)
<class 'sage.structure.sequence.Sequence_generic'>
sage: type(v[1])
<type 'sage.rings.rational.Rational'>
sage: v.universe()
Rational Field
sage: v.is_immutable()
False
sage: v.set_immutable()
sage: v[0] = 3
Traceback (most recent call last):
...


sage: v = Sequence([1,2,3,4/5])
sage: isinstance(v, list)
True
sage: list(v)
[1, 2, 3, 4/5]
sage: type(list(v))
<... 'list'>


sage: V = QQ^3; B = V.basis(); B
[
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
]
sage: type(B)
<class 'sage.structure.sequence.Sequence_generic'>
sage: B[0] = B[1]
Traceback (most recent call last):
...
sage: B.universe()
Vector space of dimension 3 over Rational Field


## 辞典¶

sage: d = {1:5, 'sage':17, ZZ:GF(7)}
sage: type(d)
<... 'dict'>
sage: list(d.keys())
[1, 'sage', Integer Ring]
sage: d['sage']
17
sage: d[ZZ]
Finite Field of size 7
sage: d[1]
5


sage: list(d.items())
[(1, 5), ('sage', 17), (Integer Ring, Finite Field of size 7)]


sage: d = {2:4, 3:9, 4:16}
sage: [a*b for a, b in d.items()]
[8, 27, 64]


## 集合¶

Python有一个内置的set类型。它提供的主要功能是快速查找元素是否在集合中，以及标准的集合论运算。

sage: X = set([1,19,'a']);   Y = set([1,1,1, 2/3])
sage: X   # random sort order
{1, 19, 'a'}
sage: X == set(['a', 1, 1, 19])
True
sage: Y
{2/3, 1}
sage: 'a' in X
True
sage: 'a' in Y
False
sage: X.intersection(Y)
{1}


Sage也有自己的set类型（在某些情况下）使用内置的Python set类型实现，但是有一些额外的Sage相关功能。使用创建Sage集 Set(...) . 例如，

sage: X = Set([1,19,'a']);   Y = Set([1,1,1, 2/3])
sage: X   # random sort order
{'a', 1, 19}
sage: X == Set(['a', 1, 1, 19])
True
sage: Y
{1, 2/3}
sage: X.intersection(Y)
{1}
sage: print(latex(Y))
\left\{1, \frac{2}{3}\right\}
sage: Set(ZZ)
Set of elements of Integer Ring


## 遍历器¶

sage: v = (n^2 for n in xrange(10000000))  # py2
sage: v = (n^2 for n in range(10000000))  # py3
sage: next(v)
0
sage: next(v)
1
sage: next(v)
4


sage: w = (4*p + 1 for p in Primes() if is_prime(4*p+1))
sage: w         # in the next line, 0xb0853d6c is a random 0x number
<generator object at 0xb0853d6c>
sage: next(w)
13
sage: next(w)
29
sage: next(w)
53


sage: [x for x in GF(7)]
[0, 1, 2, 3, 4, 5, 6]
sage: W = ((x,y) for x in ZZ for y in ZZ)
sage: next(W)
(0, 0)
sage: next(W)
(0, 1)
sage: next(W)
(0, -1)


## 循环、函数、控制语句和比较¶

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4


sage: for i in range(5):
....:     print(i)  # now hit enter twice
....:
0
1
2
3
4


sage: for i in range(15):
....:     if gcd(i,15) == 1:
....:         print(i)
....:
1
2
4
7
8
11
13
14


sage: def legendre(a,p):
....:     is_sqr_modp=-1
....:     for i in range(p):
....:         if a % p == i^2 % p:
....:             is_sqr_modp=1
....:     return is_sqr_modp

sage: legendre(2,7)
1
sage: legendre(3,7)
-1


sage: 2 < 3.1; 3.1 <= 1
True
False
sage: 2/3 < 3/2;   3/2 < 3/1
True
True


sage: x < x + 1
x < x + 1
sage: bool(x < x + 1)
True


sage: 1 is 2/2
False
sage: int(1) is int(2)/int(2)   # py2
True
sage: 1 is 1
False
sage: 1 == 2/2
True


sage: GF(5)(1) == QQ(1); QQ(1) == GF(5)(1)
False
False
sage: GF(5)(1) == ZZ(1); ZZ(1) == GF(5)(1)
True
True
sage: ZZ(1) == QQ(1)
True


sage: magma('GF(5)!1 eq Rationals()!1')            # optional - magma
true


## 分析¶

“过早的优化是万恶之源。”—唐纳德·克努斯

sage: k,a = GF(2**8, 'a').objgen()
sage: A = Matrix(k,10,10,[k.random_element() for _ in range(10*10)])

sage: %prun B = A*A
32893 function calls in 1.100 CPU seconds

Ordered by: internal time

ncalls tottime percall cumtime percall filename:lineno(function)
12127  0.160   0.000   0.160  0.000 :0(isinstance)
2000  0.150   0.000   0.280  0.000 matrix.py:2235(__getitem__)
1000  0.120   0.000   0.370  0.000 finite_field_element.py:392(__mul__)
1903  0.120   0.000   0.200  0.000 finite_field_element.py:47(__init__)
1900  0.090   0.000   0.220  0.000 finite_field_element.py:376(__compat)
900  0.080   0.000   0.260  0.000 finite_field_element.py:380(__add__)
1  0.070   0.070   1.100  1.100 matrix.py:864(__mul__)
2105  0.070   0.000   0.070  0.000 matrix.py:282(ncols)
...


As usual, prun? provides details on how to use the profiler and understand the output.

sage: %prun -r A*A
sage: stats = _
sage: stats?


sage: k,a = GF(2**8, 'a').objgen()
sage: A = Matrix(k,10,10,[k.random_element() for _ in range(10*10)])
sage: import hotshot
sage: filename = "pythongrind.prof"
sage: prof = hotshot.Profile(filename, lineevents=1)

sage: prof.run("A*A")
<hotshot.Profile instance at 0x414c11ec>
sage: prof.close()


\$ hotshot2calltree -o cachegrind.out.42 pythongrind.prof