继续学习Python:函数、文件与异常
继续学习Python:函数、文件与异常
一、函数
开始
函数可以处理一类问题,据我所知,它可以省去很多重复的代码。
def fun1(a, b, c):
dict1 = {'a': a, 'b': b, 'c': c}
return dict1
调用:
i, j, k = 1, 2, 3
dict2 = fun1(i, j, k)
print(dict2)
输出: (可以看出,字典其实是无序的。)
{'a': 1, 'c': 3, 'b': 2}
说明:
- i, j, k 调用函数时,这些叫做实参
- a, b, c 定义函数时,这些叫做形参
- a, b, c, dict1 这些都是局部变量,只在函数内部有效
- 形参一般不能改变实参,但用列表、字典作为实参时,可以直接修改。
- 一个函数最好只做一件事
形参与实参
def fun2(a, b, c, d=99):
dict1 = {'a': a, 'b': b, 'c': c, 'd': d}
return dict1
调用:
print(fun2(1, 2, 3, 4))
print(fun2(5, 6, 7))
print(fun2(a=8, c=9, b=10, d=''))
输出:
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
{'a': 5, 'c': 7, 'b': 6, 'd': 99}
{'a': 8, 'c': 9, 'b': 10, 'd': ''}
说明:
- 可以按顺序,通过位置实参来调用函数
- 也可以用a=8, b=9...通过关键字实参来调用函数
- 可以在函数定义中设置默认值(放最后),调用时可以适当省略
参数魔法
有时候,无法预知函数需要接受多少个实参,3个?5个?或者10个?都没问题!!!
任意位置实参
def fun3(a, b, *c):
print('a={}, b={}, c={}'.format(a, b, c))
调用:
fun3(1, 2, 3)
fun3(1, 2, 3, 4, 5)
输出:
a=1, b=2, c=(3,)
a=1, b=2, c=(3, 4, 5)
可以看出,多余的位置实参是用元组来收集了
任意关键字实参
def fun3(a, b, **c):
print('a={}, b={}, c={}'.format(a, b, c))
fun3(1, 2, c=3)
fun3(1, 2, c=3, d=4, e=5)
dict1 = {'c': 9, 'd': 10, 'e': 11}
fun3(1, 2, **dict1)
输出:
a=1, b=2, c={'c': 3}
a=1, b=2, c={'c': 3, 'e': 5, 'd': 4}
a=1, b=2, c={'c': 9, 'e': 11, 'd': 10}
这次,多余的关键字实参是用字典来收集的。
另外,通过dict1调用时,我用**解包了它,貌似会更好看。
二、文件
普通文本读写
先创建一个文件:
cat > file1.txt << EOF
This is line1.
This is line2.
This is line3.
EOF
读
一次读完:
with open('file1.txt') as fr:
contents = fr.read()
print(contents)
一行一行地读:
with open('file1.txt') as fr:
for line in fr.readlines():
print(line)
或者存进列表中:
with open('file1.txt') as fr:
lines = fr.readlines()
for line in lines:
print(line)
写
为每行添加行号:
with open('file1.txt') as fr:
with open('file2.txt', 'w') as fw:
i = 1
for line in fr.readlines():
fw.write(str(i) + ' ' + str(line))
i += 1
一次写入多行用: writelines()
json文件读写
JSON数据格式是通用的数据存储格式,我知道它可以用来储存列表、字典、数值,足矣。
写
import json
dict1 = {'numbers': [x for x in range(10)],
'a-tuple': (1, 2, 3), 'a-dict': {'a': 1, 'b': 2}}
filename = 'file1.json'
with open(filename, 'w') as fw:
json.dump(dict1, fw)
查看文件file1.json:
{"numbers": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "a-tuple": [1, 2, 3], "a-dict": {"a": 1, "b": 2}}
读
with open(filename) as fr:
dict2 = json.load(fr)
dict2
输出如下:
{'numbers': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
'a-tuple': [1, 2, 3],
'a-dict': {'a': 1, 'b': 2}}
看起来,jupyter的排版是挺美观的。
csv文件读写
新建一个文件file1.csv:
name,sex,age,address,job
li,male,20,xiaoshi,IT
zhang,female,22,xiaoshi,Teacher
liu,female,30,zhouxin,doctor
读
filecsv = 'file1.csv'
with open(filecsv) as fr:
reader = csv.reader(fr)
header_row = next(reader)
# print(header_row)
for row in reader:
print(row)
输出:
['li', 'male', '20', 'xiaoshi', 'IT']
['zhang', 'female', '22', 'xiaoshi', 'Teacher']
['liu', 'female', '30', 'zhouxin', 'doctor']
next(): 读一行,并指向下一行
写
list1 = [x for x in range(10)]
with open('file2.csv', 'w') as fw:
writer = csv.writer(fw)
writer.writerow(list1)
查看file2.csv:
0,1,2,3,4,5,6,7,8,9
读取csv数据,并绘图
这里有一个csv文件(4.gz),它只有一行,不知道有多少个数,反正读取出来并绘图。
import matplotlib.pyplot as plt
import csv
import numpy as np
with open('4.gz') as fr:
reader = csv.reader(fr)
data = next(reader)
# for i, v in enumerate(data):
# data[i] = float(v)
data = list(map(float, data))
x = np.arange(1, len(data)+1, 1)
y = np.array(data)
print(y.min(), y.max(), y.max()-y.min())
plt.plot(x, y, linewidth=2)
plt.title("Title", fontsize=24)
plt.xlabel("x", fontsize=14)
plt.ylabel("y", fontsize=14)
plt.tick_params(axis='both', labelsize=24)
plt.show()
输出: -0.02 0.2 0.22
以及 一张图:
说明:这里提到的作图库matplotlib、数学库numpy以后再写。
三、异常
概念
异常按字面理解,就是发生了不正常的事情。
比如:1/0
ZeroDivisionError Traceback (most recent call last)
<ipython-input-1-9e1622b385b6> in <module>
----> 1 1/0
ZeroDivisionError: division by zero
常见异常
异常代码 | 异常名称 | 原因 |
---|---|---|
1/0 | ZeroDivisionError | 0不能被除 |
open('haha.txt') | FileNotFoundError | 读不存在的文件 |
1 + 'a' | TypeError | 类型不符合 |
dict1={} ; dict1['a'] | KeyError | 不存在的键 |
list1 = [1, 2, 3] ; list1[3] | IndexError | 访问越界 |
dict1['a'] = b | NameError | 变量未定义 |
程序遇到异常一般会直接打印异常信息并退出,有时候我们并不想直接退出,只是想忽略,或者扫尾再退出。 |
list1 = ['file1.txt', 'file2.txt', 'file3.txt']
for filename in list1:
try:
with open(filename) as fr:
print('{}: {}'.format(filename, fr.read(10)))
except FileNotFoundError:
pass
输出:
file1.txt: This is li
file2.txt: 1 This is
以上,每个文件读10个字节,并打印出来,遇到不存在的文件直接跳过,不打印任何信息。
常用处理方法
常用这样的结构处理异常: try - except - else - finally
dict1 = {};
list1 = [1, 2, 3]
code_list = ["1/0", "1+1", "open('haha.txt')", "1 + 'a'",
"dict1['a']", "dict1['a'] = b", "list1[3]=99"]
for x in code_list:
try:
exec(x)
except FileNotFoundError:
print(x + ': I catch FileNotFoundError')
except Exception as e:
print('{}: {}'.format(x, repr(e)))
else: # 记住,是try成功,对!是try成功执行后,才会到这里!!!
print(x + ': ok.')
finally:
print('') # 打印一空行
输出:
1/0: ZeroDivisionError('division by zero')
1+1: ok.
open('haha.txt'): I catch FileNotFoundError
1 + 'a': TypeError("unsupported operand type(s) for +: 'int' and 'str'")
dict1['a']: KeyError('a')
dict1['a'] = b: NameError("name 'b' is not defined")
list1[3]=99: IndexError('list assignment index out of range')
说明:
- exec(x): 执行字符串x中的代码
- try: 直接运行,错了再说。其实这样做,可以省去许多if-else
- except: 错了就在这里捕获异常,可以忽略异常,或者扫尾后退出
- else: try成功后,到else继续执行
- finally: 最后执行它,可以用来扫尾什么的。上面示例代码只打印一空行
- repr(e): 比str(e)多了异常名称(IndexError...)
下期预告:继续学习Python.