语法基础
异常处理
def factorial(x):
if x < 0:
raise Exception("Invalid input to factorial")
if x == 0:
return 1
return x * factorial(x-1)
用raise抛出一个exception异常
输出
print(x[1:]) # Take all elements from the first one onwards
print(x[2:4]) # Take elements 2 and 3 (we do not take last member of sequence)
for循环
实际上'range(x)' 相当于 list [0,1,..,x-1].
注意:range(起始,终止,步长)取不到右端点值,所以我们要写range(1,10,2)而非range(1,9,2)
for i in range(1,x+1):
total = total * i
# Or even a 'step' size as a third argument, so we could get the odd numbers between 1 and 9 by writing
range(1,10,2)
dict()
类似c++中的map,存储key和对应的value,
# In the next section we will want to use a 'dict' to store value we are caching.
# A dict is a map from keys to values
# Create a dict
name = dict()
name["Chris"] = "Jefferson"
print("Chris" in name)
print("Karen" in name)
print(name["Chris"])
我在name中存储了key为"Chris";value为"jefferson"。结果如下
部分运行用shift+enter,撤回用ctrl+z
元组和列表
元组使用小括号,列表使用中括号
# Values in dicts must be immutable (cannot be changed). Lists are mutable, so we cannot use them as keys
# name[ [1,2,3] ] = 6 <-- This would produce an error.
# In Python, lists which cannot change (are immutable) are called tuples, and they are made with round brackets
name[ (1,2,3) ] = 6 # Works fine
# If we have a list, we can turn it into a tuple using 'tuple'
l = [1,2,3]
print(name[tuple(l)]) # Prints '6'
字典中key的value不可以改变,列表中的元素值可以改变,所以显然我们不可以把列表作为dict()的key值。元组tuple则可以当作key值,它的元素不可以改变。
列表的增删
两个list合并
# You can add lists together using '+'
x = [4,5,6,7,8,9]
y = [6,5]
print(x+y)
用appent()添加
# Or we can add an element to a list using 'append'
x.append(2)
print(x)
编码技巧
循环的简写
in_list = [2,3,4,5,6]
out_list = []
for i in in_list:
out_list.append(i*i)
print(out_list)
# We can write this as:
other_out_list = [i*i for i in in_list]
print(other_out_list)
组合数学
阶乘
递归实现
def factorial(x):
if x == 0:
return 1
return x * factorial(x-1)
循环实现
for
def factorial_for(x):
total = 1
for i in range(x):
total = total * (i + 1)
return total
while
def factorial_while(x):
total = 1
while x > 0:
total = total * x
x = x - 1
return total
部分阶乘
递归实现
def falling_factorial(n,k):
return factorial(n)//factorial(n-k)
循环实现
# Technically, it is a bit of a waste to calculate the two factorials, as lots of terms end up cancelling out, so we can instead only ltiply the terms we need. Notice how the 'range' here is a bit tricky
def falling_factorial_for(n,k):
total = 1
for i in range(n-k+1, n+1):
total = total * i
return total
# We could implement this another way:
def falling_factorial_for_2(n, k):
result = 1
for i in range(k):
result *= n
n -= 1
return result
组合数公式
def choose(n,k):
return factorial(n)//(factorial(n-k) * factorial(k))
注意:为了答案是整数用整除,否则是x.0的形式
阶乘之间的乘除
用list列表
# Here, the second argument is a list
def multinomial(n, list):
top = factorial(n)
bottom = 1
# We can iterate through lists, performing a calculation at every step
for k in list:
bottom *= factorial(k)
return top//bottom
print(multinomial(8,[3,3,2]))
8的阶乘/(3的阶乘*3的阶乘*2的阶乘)
'squig'数
用squig数的递归定义
# Let us now try defining 'squig'.
# While this produces the right answer, it will be very slow for larger values
def squig(s,t):
if s == 0:
return (t == 0)
if t < 0:
return 0
return t*squig(s-1,t) + squig(s-1,t-1)
squig(10,2)
用全局变量作为"寄存器"
squig_cache = dict()
def squig(s,t):
if s == 0:
return (t == 0)
if t < 0:
return 0
global squig_cache
if (s,t) in squig_cache:
return squig_cache[(s,t)]
ret = t*squig(s-1,t) + squig(s-1,t-1)
squig_cache[(s,t)] = ret
return ret
相当于c++中的记忆化搜索
用类实现
# This use of a global variable is not very neat. We would be better using a class
class Squig:
def __init__(self):
self.cache = dict()
def get(self, s,t):
if s == 1:
return (t==1)
if t < 0:
return 0
if (s,t) in self.cache:
return self.cache[(s,t)]
ret = t*self.get(s-1,t) + self.get(s-1,t-1)
self.cache[(s,t)] = ret
return ret
s = Squig()
s.get(10,2)
贝尔数的计算
# Calculating the 'bell' number will take a very long time to run (4 seconds on my computer for bell(20)), as 'squig' is too slow
def bell(s):
return sum([squig(s,k) for k in range(s+1)])
print(bell(20))
例题
1.求集合的子集
# How can we find all subsets of a set. We can do this recursively
def all_subsets_of(list):
# The empty set has only a single subset -- the empty set!
if list == []:
return [ [] ]
else:
# list[1:] takes the list ignoring the first element
no_first = all_subsets_of(list[1:])
others = []
for l in no_first:
others.append([list[0]] + l)
return no_first + others
all_subsets_of([1,2,3])
递归实现将n-1个元素的子集加上添加进第n个元素之后新增的集合
2.如果我们限制输出的子集的大小
def all_subsets_of_size_k(list, k):
#特殊条件处理
# If we want sets of size '0', there is just the empty set.
if k == 0:
return [ [] ]
# If the list has less than 'k' members, then we can't make any sets of size k
if len(list) < k:
return []
#其他(与上面一样)
part1 = all_subsets_of_size_k(list[1:], k)
# sets of size k-1 which do not include list[0], which we will then add 'list[0]' to
part2 = all_subsets_of_size_k(list[1:], k-1)
part2withk = []
for l in part2:
part2withk.append([list[0]] + l)
return part1 + part2withk
all_subsets_of_size_k([1,2,3,4], 2)