本文从 洛谷 P1001 A+B Problem 为例,讲一讲 Python 3 在算法竞赛中的一些基本输入输出方法,以及一些利用 Python 3 特性的代码简化
以下为本文将涉及的内容:
-
input()
-
str.split()
-
print()
-
map()
-
[... for ... in ...]
list 构造方法 -
sum()
直接看到题目:输入两个整数,以空格隔开,输出他们的和
于是我们要先解决第一个问题:
如何输入
根据输入格式,题目输入两个整数,由空格隔开
如输入样例
20 30
而 Python 3 的 input()
函数是读入一行,如 IDLE 的调试(遇到问题都可以试试 IDLE 哦)
>>> a=input()
20 30
>>> type(a)
<class 'str'>
>>> a
'20 30'
所以 input()
返回一个字符串,内容为输入的一行
但是我们想要的是输入的整数啊
int
为整数的类型符,作为函数时表示为强制转换
>>> a='20'
>>> type(a)
<class 'str'>
>>> b=int(a)
>>> type(b)
<class 'int'>
>>> b
20
但是我们输入的整数之间有空格,导致报错
>>> a='20 30'
>>> int(a)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
int(a)
ValueError: invalid literal for int() with base 10: '20 30'
所以我们需要把输入的数据给分开
如何分割
Python 3 提供了 str.split()
方法,把输入的字符串按照空格,换行符,制表符等分割为由字符串组成的列表
>>> a=input()
python 3
>>> a
' python 3'
>>> b=a.split()
>>> type(b)
<class 'list'>
>>> b
['python', '3']
可以发现,空格符等符号在 split()
之后就消除了
另外,split()
作为 str
类的一个成员方法,而 input()
本身就返回 str
类,所以可以直接简写成 input().split()
>>> a=input().split()
python 3 666
>>> a
['python', '3', '666']
这样,我们是不是就可以解决题目了?
>>> s=input().split()
20 30
>>> s
['20', '30']
因为列表里下标从0开始计数,所以 s[0]
, s[1]
分别是输入的两个数字,加起来不就是答案了?
>>> s[0]+s[1]
'2030'
不对!(s) 是由字符串组成的列表,而字符串加法仅仅是拼接而已
所以得用 int()
强制转为整数
>>> int(s[0])+int(s[1])
50
终于答案对了,所以之后是
如何输出
题目要求输入完整的 Python 3 代码文件,所以得用 print()
函数完成输出
以下是 .py 文件的内容(可以发现这就是洛谷给出的答案)
s=input().split()
print(int(s[0])+int(s[1]))
在输入样例时,输出结果为
50
(大家可以使用洛谷 IDE 或自己的 IDLE 的文件模式进行调试)
所以 print()
函数会在末尾给出换行,而在算法竞赛中,评测姬一般不考虑行末空格以及文末换行,所以这样没问题
如果想去掉换行可以使用
print(int(s[0])+int(s[1]),end="")
而后面的 end=""
就表示输出后不在末尾加任何东西,当然如果写成 end=" "
,那么就会在末尾加上空格
以下是:
拓展时间
单单这样可以解决 A+B Problem,但是每次都使用 int()
强制转换未免有点麻烦,所以我们引出
map()
函数
map()
函数接收一个函数和一个列表,返回一个列表的迭代器(这是 Python 3 节省时间空间的办法,可以理解为这个列表的所在位置),其中这个列表的元素是输入 map()
的列表里每一个元素作用一遍前面的函数之后的返回值
是不是有点懵,来看一个例子(以下为 .py 文件内容):
def sq(x):
return x**2
a=[1,2,3,4,5]
b=map(sq,a)
print(b)
以下为输出:
<map object at 0x000001C807DD4AC0>
呃……这是迭代器,如果想知道原来的内容应该用 list()
强制转换
def sq(x):
return x**2
a=[1,2,3,4,5]
b=list(map(sq,a))
print(b)
以下为输出:
[1, 4, 9, 16, 25]
所以我们先定义 (sq()) 表示对输入的数字进行平方,然后用 map()
把 (a) 里的所有元素都进行了 (sq()),最后把结果变成 list
给 (b),就得到了想要的答案
那我们不就可以用 map()
把 split()
之后由字符串组成的列表变成由数字组成的列表了吗?(以下为 IDLE 调试内容)
>>> a=input().split()
20 30
>>> b=list(map(int,a))
>>> b
[20, 30]
可以看见 int()
强制转换函数也适用,这样的话直接做加法就没问题了
>>> b[0]+b[1]
50
所以这样写也是正确答案:
a=list(map(int,input().split()))
print(a[0]+a[1])
除了 map()
函数可以帮忙做群体变换,还有一种方法,那就是
[... for ... in ...]
list 构造方法
[f(x) for x in a]
返回一个列表,其中 (x) 为任意变量名,(a) 为一个列表,(f(x)) 为一个可以包含 (x) 的表达式(就是说不一定要包含 (x))
举个例子:
>>> a=[x**2 for x in [1,2,3,4,5]]
>>> a
[1, 4, 9, 16, 25]
>>> b=[0 for y in [1,2,3,4,5]]
>>> b
[0, 0, 0, 0, 0]
在这种构造方法中,不需要定义函数(如之前 map()
演示中的 (sq())),而且直接返回列表而不是迭代器,所以 [f(x) for x in a]
等价于 list(map(f,a))
总的来说,如果直接使用函数,map()
更方便,如果是表达式,[... for ... in ...]
更方便
最后引进我们的重头戏
一行完成 A+B problem
其实,Python 3 里面有 sum()
函数,输入一个数字列表,输出所有元素的求和
>>> sum([1,2,3,4])
10
而进行了 map()
操作之后的列表正好就是数字列表,可以直接使用 sum()
>>> sum(map(int,input().split()))
20 30
50
是不是瞬间得到答案?(注意这里的 map()
之外可以不加 list()
,因为 sum()
本身支持输入列表的迭代器)
所以以下就是我们的一行 AC 代码:
print(sum(map(int,input().split())))
当然还有使用 [... for ... in ...]
构造方法的版本:
print(sum([int(x) for x in input().split()]))
另外这还有一个好处,就是不管输入几个由空格连接的数字,它都能输出所有数字的和(想想为什么)
在看似杂乱的括号和函数之间存在章法,这正是代码的精髓所在
那么本文的内容就到此结束啦,感谢大家的观看,也请各路大佬多多指教!