Solution & Method: 洛谷 P1001 A+B Problem(Python 3 基本输入输出方法及代码简化)

本文从 洛谷 P1001 A+B Problem 为例,讲一讲 Python 3 在算法竞赛中的一些基本输入输出方法,以及一些利用 Python 3 特性的代码简化

以下为本文将涉及的内容:

  1. input()

  2. str.split()

  3. print()

  4. map()

  5. [... for ... in ...] list 构造方法

  6. 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()]))

另外这还有一个好处,就是不管输入几个由空格连接的数字,它都能输出所有数字的和(想想为什么)

在看似杂乱的括号和函数之间存在章法,这正是代码的精髓所在

那么本文的内容就到此结束啦,感谢大家的观看,也请各路大佬多多指教!

posted @ 2020-12-23 09:35  BrianPeng  阅读(853)  评论(0编辑  收藏  举报