继续学习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.

posted @ 2020-05-04 11:29  qydw007  阅读(130)  评论(0编辑  收藏  举报