"""
输入 m 和 n,计算组合数 C(m,n) 的值
"""
m = int(input('m = '))
n = int(input('n = '))
# 计算 m 的阶乘
fm = 1for num inrange(1, m + 1):
fm *= num
# 计算 n 的阶乘
fn = 1for num inrange(1, n + 1):
fn *= num
# 计算 m-n 的阶乘
fk = 1for num inrange(1, m - n + 1):
fk *= num
# 计算 C(M,N) 的值print(fm // fn // fk)
输入:
m = 7n = 3
输出:
35
不知大家是否注意到,上面的代码中我们做了三次求阶乘的操作,虽然 m、n、m-n 的值各不相同,但是三段代码并没有实质性的区别,属于重复代码。世界级的编程大师 Martin Fowler 曾经说过:'代码有很多种坏味道,重复是最坏的一种!'。要写出高质量的代码,首先就要解决重复代码的问题。对于上面的代码来说,我们可以将求阶乘的功能封装到一个称为'函数'的代码块中,在需要计算阶乘的地方,我们只需'调用函数'即可实现对求阶乘功能的复用。
"""
输入 m 和 n,计算组合数 C(m,n) 的值
"""# 通过关键字 def 定义求阶乘的函数# 自变量(参数)num 是一个非负整数# 因变量(返回值)是 num 的阶乘deffac(num):
result = 1for n inrange(2, num + 1):
result *= n
return result
m = int(input('m = '))
n = int(input('n = '))
# 计算阶乘的时候不需要写重复的代码而是直接调用函数# 调用函数的语法是在函数名后面跟上圆括号并传入参数print(fac(m) // fac(n) // fac(m - n))
大家可以感受下,上面的代码是不是比之前的版本更加简单优雅。更为重要的是,我们定义的求阶乘函数 fac 还可以在其他需要求阶乘的代码中重复使用。所以,使用函数可以帮助我们将功能上相对独立且会被重复使用的代码封装起来,当我们需要这些的代码,不是把重复的代码再编写一遍,而是通过调用函数实现对既有代码的复用。事实上,Python 标准库的 math 模块中,已经有一个名为 factorial 的函数实现了求阶乘的功能,我们可以直接用 import math 导入 math 模块,然后使用 math.factorial 来调用求阶乘的函数;我们也可以通过 from math import factorial 直接导入 factorial 函数来使用它,代码如下所示。
"""
输入 m 和 n,计算组合数 C(m,n) 的值
"""from math import factorial
m = int(input('m = '))
n = int(input('n = '))
print(factorial(m) // factorial(n) // factorial(m - n))
将来我们使用的函数,要么是自定义的函数,要么是 Python 标准库或者三方库中提供的函数,如果已经有现成的可用的函数,我们就没有必要自己去定义,'重复发明轮子'是一件非常糟糕的事情。对于上面的代码,如果你觉得 factorial 这个名字太长,书写代码的时候不是特别方便,我们在导入函数的时候还可以通过 as 关键字为其别名。在调用函数的时候,我们可以用函数的别名,而不再使用它之前的名字,代码如下所示。
"""
输入 m 和 n,计算组合数 C(m,n) 的值
"""from math import factorial as f
m = int(input('m = '))
n = int(input('n = '))
print(f(m) // f(n) // f(m - n))
# /前面的参数是强制位置参数defmake_judgement(a, b, c, /):
"""判断三条边的长度能否构成三角形"""return a + b > c and b + c > a and a + c > b
# 下面的代码会产生 TypeError 错误,错误信息提示'强制位置参数是不允许给出参数名的'# print(make_judgement(b=2, c=3, a=1))
# *后面的参数是命名关键字参数defmake_judgement(*, a, b, c):
"""判断三条边的长度能否构成三角形"""return a + b > c and b + c > a and a + c > b
# 下面的代码会产生 TypeError 错误,错误信息提示'函数没有位置参数但却给了 3 个位置参数'# print(make_judgement(1, 2, 3))
from random import randrange
# 定义摇色子的函数# 函数的自变量(参数)n 表示色子的个数,默认值为 2# 函数的因变量(返回值)表示摇 n 颗色子得到的点数defroll_dice(n=2):
total = 0for _ inrange(n):
total += randrange(1, 7)
return total
# 如果没有指定参数,那么 n 使用默认值 2,表示摇两颗色子print(roll_dice())
# 传入参数 3,变量 n 被赋值为 3,表示摇三颗色子获得点数print(roll_dice(3))
我们再来看一个更为简单的例子。
defadd(a=0, b=0, c=0):
"""三个数相加求和"""return a + b + c
# 调用 add 函数,没有传入参数,那么 a、b、c 都使用默认值 0print(add()) # 0# 调用 add 函数,传入一个参数,该参数赋值给变量 a,变量 b 和 c 使用默认值 0print(add(1)) # 1# 调用 add 函数,传入两个参数,分别赋值给 a 和 b,变量 c 使用默认值 0print(add(1, 2)) # 3# 调用 add 函数,传入三个参数,分别赋值给 a、b、c 三个变量print(add(1, 2, 3)) # 6
Python 标准库中提供了大量的模块和函数来简化我们的开发工作,我们之前用过的 random 模块就为我们提供了生成随机数和进行随机抽样的函数;而 time 模块则提供了和时间操作相关的函数;我们之前用到过的 math 模块中还包括了计算正弦、余弦、指数、对数等一系列的数学函数。随着我们深入学习 Python 语言,我们还会用到更多的模块和函数。