Python编程
输入
Python 3.x 有一个用于接收用户输入的函数 input()
。与此相对,旧版 Python 2.x 有两个用于接收用户输入的函数:input()
和 raw_input()
。
Python 3.x 中的 input()
在 Python 3.x 中,input()
会请求用户输入一个字符串(以换行符结束),并简单地返回该字符串。它也可以接收一个参数,作为在用户输入数据前显示的提示。例如:
print(input('What is your name?'))
将输出:
What is your name? <用户输入的内容>
例如,如果你想将用户的名字(即字符串数据)赋值给变量 "x",可以这样写:
x = input('What is your name?')
在 Python 2.x 中,以上代码适用于 raw_input()
函数,而 input()
函数的行为不同,会自动评估用户输入的内容;在 Python 3 中,可以通过 eval(input())
来实现相同的效果。
【链接】:
- input() in Built-in Functions in Library Reference for Python 3
- raw_input() in Built-in Functions in Library Reference for Python 2
Python 2.x 中的 input()
在旧版 Python 2.x 中,input()
会将用户输入的数据作为字符串并进行评估。
因此,如果脚本中写道:
x = input('What are the first 10 perfect squares? ')
用户输入的内容可能是:
map(lambda x: x*x, range(10))
这将返回正确的答案(以列表形式)。请注意,输入的语句不能跨越多行。
由于 input()
使用 eval()
将字符串转换为 Python 类型,可能会导致安全隐患。出于安全原因,input()
不应该用于除了最简单的程序之外的任何地方。推荐使用如下习惯:
x = None
while not x:
try:
x = int(raw_input())
except ValueError:
print('Invalid Number')
这样做可以避免 input()
使用 eval()
来执行恶意代码。
【链接】:
文件输入
文件对象
f = open('test.txt', 'r')
for line in f:
print(line[0])
f.close()
这会打印出每一行的第一个字符。使用 open
的第二个参数可以是 'r'(读取)、'w'(写入)或 'rw'(读写)等。
更好的读取文件方式是:
with open("test.txt", "r") as txt:
for line in txt:
print(line)
优点是文件在 with
语句块结束后会自动关闭,即使发生异常也会关闭文件。
因为文件在文件对象超出作用域时会自动关闭,所以实际上不需要显式调用 close()
。因此,上述代码的循环也可以改写为:
for line in open('test.txt', 'r'):
print(line[0])
你可以一次读取特定数量的字符:
c = f.read(1)
while len(c) > 0:
if len(c.strip()) > 0: print(c)
c = f.read(1)
这会逐个读取文件中的字符,并打印出非空白字符。
文件对象隐式包含一个标记,用于表示当前位置。如果要将文件标记移动回开始位置,可以通过以下代码实现:
f.seek(0)
标准文件对象
Python 提供了代表标准输入、输出和错误的内建文件对象。这些对象位于 sys
模块中,分别称为 stdin
、stdout
和 stderr
。在 IDLE 和其他工具中,这些文件对象的副本为 __stdin__
、__stdout__
和 __stderr__
,它们用于处理已更改的标准文件。
要使用这些特殊的 stdin
、stdout
、stderr
输入输出句柄,必须导入 sys
模块:
import sys
对于更精细的输入控制,可以使用 sys.stdin.read()
。例如,下面的代码实现了 UNIX 的 cat
命令:
import sys
for line in sys.stdin:
print(line, end="")
sys.stdin.read()
会读取标准输入直到 EOF(通常是 Ctrl+D)。
解析命令行参数
传递给 Python 程序的命令行参数存储在 sys.argv
列表中。该列表的第一个项是 Python 程序的名称,可能包含完整路径,具体取决于调用方式。sys.argv
列表是可修改的。
打印出除程序名称之外的所有传递参数:
import sys
for arg in sys.argv[1:]:
print(arg)
解析传递的参数和选项:
import sys
option_f = False
option_p = False
option_p_argument = ""
i = 1
while i < len(sys.argv):
if sys.argv[i] == "-f":
option_f = True
sys.argv.pop(i)
elif sys.argv[i] == "-p":
option_p = True
sys.argv.pop(i)
option_p_argument = sys.argv.pop(i)
else:
i += 1
在上面的代码中,找到的选项参数会被删除,这样 sys.argv
就可以用于循环遍历所有剩余的参数。
命令行参数的解析通过库模块 optparse
(已弃用)、argparse
(自 Python 2.7 起支持)和 getopt
(便于 C 程序员使用)提供了进一步的支持。
使用 argparse
进行解析的最小示例:
import argparse
parser = argparse.ArgumentParser(description="连接两个字符串")
addarg = parser.add_argument
addarg("s1", help="第一个字符串")
addarg("s2", help="第二个字符串")
args = parser.parse_args()
result = args.s1 + args.s2
print(result)
使用 argparse
解析时指定参数类型为整数:
import argparse
parser = argparse.ArgumentParser(description="求和两个整数")
addarg = parser.add_argument
addarg("i1", help="第一个整数", type=int)
addarg("i2", help="第二个整数", type=int)
args = parser.parse_args()
result = args.i1 + args.i2
print(result)
使用 argparse
添加可选开关 -m
来执行乘法而不是加法:
import argparse
parser = argparse.ArgumentParser(description="对两个整数求和或相乘")
addarg = parser.add_argument
addarg("i1", help="第一个整数", type=int)
addarg("i2", help="第二个整数", type=int)
addarg("-m", help="执行乘法而不是加法", action="store_true")
args = parser.parse_args()
if args.m:
result = args.i1 * args.i2
else:
result = args.i1 + args.i2
print(result)
使用 argparse
设置一个参数,接受一个或多个值:
import argparse
parser = argparse.ArgumentParser(description="求和一个或多个整数")
addarg = parser.add_argument
addarg("intlist", help="整数", type=int, nargs="+")
args = parser.parse_args()
result = 0
for item in args.intlist:
result += item
print(result)
使用示例:python ArgparseTest.py 1 3 5
使用 argparse
设置帮助信息(epilog)显示在 -h
后:
import argparse
parser = argparse.ArgumentParser(description="求和一个或多个整数",
epilog="示例:python ArgparseTest.py 1 3 5")
addarg = parser.add_argument
addarg("intlist", help="整数", type=int, nargs="+")
args = parser.parse_args()
result = 0
for item in args.intlist:
result += item
print(result)
使用 argparse
设置第二个整数参数为可选,通过 nargs
设置:
import argparse
parser = argparse.ArgumentParser(description="求和一个或两个整数",
epilog="示例:python ArgparseTest.py 3 4\n"
"示例:python ArgparseTest.py 3")
addarg = parser.add_argument
addarg("i1", help="第一个整数", type=int)
addarg("i2", help="第二个整数,可选,默认值为 1", type=int, default=1, nargs="?")
args = parser.parse_args()
result = args.i1 + args.i2
print(result)
【链接】:
- The Python Standard Library - 28.1. sys
- The Python Standard Library - 15.4. argparse
- The Python Standard Library - 15.5. optparse
- The Python Standard Library - 15.6. getopt
- Argparse Tutorial
输出
输出的基本方式是使用 print
语句:
print('Hello, world')
如果要在同一行上打印多个内容并用空格分隔它们,可以使用逗号:
print('Hello,', 'World')
这将输出:
Hello, World
尽管两个字符串中没有空格,print
语句由于逗号的作用,添加了一个空格。可以打印任意数据类型:
print(1, 2, 0xff, 0777, 10+5j, -0.999, map, sys)
这将输出:
1 2 255 511 (10+5j) -0.999 <built-in function map> <module 'sys' (built-in)>
如果要在同一行中打印多个对象,并且不想自动换行,可以使用 end=" "
来指定不换行:
for i in range(10):
print(i, end=" ")
这将输出:
0 1 2 3 4 5 6 7 8 9
要在打印的行末加上换行,可以在 print
语句后再加一个 print()
:
for i in range(10):
print(i, end=" ")
print()
for i in range(10, 20):
print(i, end=" ")
这将输出:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
如果没有裸 print()
,上面的输出将变成:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
你还可以将输出打印到文件中,而不是标准输出:
print('Hello, world', file=f)
这将打印到任何实现了 write()
方法的对象,包括文件对象。
【Python 2 说明】: 在 Python 2 中,print
是一个语句,而不是函数,因此不需要在其参数周围加括号。对于 print i,
(加上逗号)会在同一行打印内容,而不会换行。
省略换行符
在 Python 3.x 中,可以通过将 end=""
传递给 print
函数来输出而不换行,或者使用 write
方法:
import sys
print("Hello", end="")
sys.stdout.write("Hello") # 或者 stderr 用于输出到标准错误流。
在 Python 2.x 中,为了避免在多个打印语句之间添加空格和换行,可以使用以下方式之一:
- 连接字符串:将每个对象的字符串表示连接起来,然后最后一次性打印出来:
print(str(1)+str(2)+str(0xff)+str(0777)+str(10+5j)+str(-0.999)+str(map)+str(sys))
这将输出:
12255511(10+5j)-0.999<built-in function map><module 'sys' (built-in)>
- 写入函数:你可以为
sys.stdout.write
创建一个快捷方式,并用它来输出:
import sys
write = sys.stdout.write
write('20')
write('05\n')
这将输出:
2005
如果需要快速在屏幕上显示文本,可能需要 sys.stdout.flush()
。
示例:Python 3.x 输出
from __future__ import print_function
# 确保 Python 2.6 和以后的 Python 2.x 可以使用 Python 3.x 的 print 函数
print("Hello", "world")
这会打印两个单词并用空格分开。注意括号在 Python 2.x 中未使用。
print("Hello world", end="")
# 打印没有换行
print("Hello", "world", sep="-")
# 打印两个单词并用破折号分隔
print("Hello", 34)
# 打印不同数据类型的元素,用空格分隔
print("Hello " + 34)
# 会抛出错误,因为尝试将字符串和整数连接
print("Hello " + str(34))
# 使用 "+" 将字符串连接,先将数字转换为字符串
sum = 2 + 2
print("The sum: %i" % sum)
# 使用格式化输出,打印整数
print("Error", file=sys.stderr)
# 输出到文件句柄,在这种情况下是标准错误流
示例:Python 2.x 输出
print "Hello"
print "Hello", "world"
# 用空格分隔两个单词
print "Hello", 34
# 打印不同数据类型的元素,用空格分隔
print "Hello " + 34
# 会抛出错误,因为尝试将字符串和整数连接
print "Hello " + str(34)
# 使用 "+" 将字符串连接,先将数字转换为字符串
print "Hello",
# 打印 "Hello ",没有换行,末尾有一个空格
sys.stdout.write("Hello")
# 打印 "Hello" 没有换行。需要 "import sys"。
# 需要随后的 "sys.stdout.flush()" 来立即显示
sys.stdout.write("Hello\n")
# 打印 "Hello" 并换行
print >> sys.stderr, "An error occurred."
# 输出到标准错误流
sys.stderr.write("Hello\n")
# 输出到标准错误流
sum = 2 + 2
print "The sum: %i" % sum
# 格式化输出,打印整数
formatted_string = "The sum: %i" % (2 + 2)
print formatted_string
# 格式化在 print 语句外部进行
print "Float: %6.3f" % 1.23456
# 输出 "Float: 1.234",数字后的 3 表示显示的数字精度为小数点后 3 位,6 表示显示的总字符数(不够则填充空格)
print "%s is %i years old" % ("John", 23)
# 将两个参数传递给格式化函数
文件输出
将数字 1 到 10 打印到文件中,每行一个:
file1 = open("TestFile.txt", "w")
for i in range(1, 10 + 1):
print(i, file=file1)
file1.close()
使用 "w"
,文件会以写入模式打开,file=file1
表示打印的输出会发送到文件而不是标准输出。
将数字 1 到 10 打印到文件中,用破折号分隔:
file1 = open("TestFile.txt", "w")
for i in range(1, 10 + 1):
if i > 1:
file1.write("-")
file1.write(str(i))
file1.close()
打开文件用于追加而不是覆盖:
file1 = open("TestFile.txt", "a")
在 Python 2.x 中,重定向到文件的方式是:print >>file1, i
。
格式化
使用字符串百分号运算符格式化数字和其他值为字符串:
v1 = "Int: %i" % 4 # 4
v2 = "Int zero padded: %03i" % 4 # 004
v3 = "Int space padded: %3i" % 4 # 4
v4 = "Hex: %x" % 31 # 1f
v5 = "Hex 2: %X" % 31 # 1F - 大写的 F
v6 = "Oct: %o" % 8 # 10
v7 = "Float: %f" % 2.4 # 2.400000
v8 = "Float: %.2f" % 2.4 # 2.40
v9 = "Float in exp: %e" % 2.4 # 2.400000e+00
vA = "Float in exp: %E" % 2.4 # 2.400000E+00
vB = "List as string: %s" % [1, 2, 3]
vC = "Left padded str: %10s" % "cat"
vD = "Right padded str: %-10s" % "cat"
vE = "Truncated str: %.2s" % "cat"
vF = "Dict value str: %(age)s" % {"age": 20}
vG = "Char: %c" % 65 # A
vH = "Char: %c" % "A" # A
使用 format()
字符串方法来格式化数字和其他值为字符串,自 Python 2.6 起支持:
v1 = "Arg 0: {0}".format(31) # 31
v2 = "Args 0 and 1: {0}, {1}".format(31, 65)
v3 = "Args 0 and 1: {}, {}".format(31, 65)
v4 = "Arg indexed: {0[0]}".format(["e1", "e2"])
v5 = "Arg named: {a}".format(a=31)
v6 = "Hex: {0:x}".format(31) # 1f
v7 = "Hex: {:x}".format(31) # 1f - arg 0 是隐式的
v8 = "Char: {0:c}".format(65) # A
v9 = "Hex: {:{h}}".format(31, h="x") # 1f - 嵌套求值
使用 Python 3.6 起的字面量字符串插值来格式化数字和其他值为字符串:
int1 = 31; int2 = 41; str1 = "aaa"; myhex = "x"
v1 = f"Two ints: {int1} {int2}"
v2 = f"Int plus 1: {int1 + 1}" # 32 - 表达式求值
v3 = f"Str len: {len(str1)}" # 3 - 表达式求值
v4 = f"Hex: {int1:x}" # 1f
v5 = f"Hex: {int1:{myhex}}" # 1f - 嵌套求值