完全掌握Python(四)

本文详细介绍python中的集合,字典,以及异常处理


集合

集合的特点:

  • 无序,不能通过index访问
  • 不重复,只保留唯一项

numbers = [1, 1, 2, 3, 4]

first = set(numbers)

print(first)

# 去掉1个重复的1后输出 {1, 2, 3, 4}

second = {1, 5}

print(first | second)

# 并集。两个集合的所有合集。{1, 2, 3, 4, 5}

print(first & second)

# 交集。同时存在于两个集合中的。{1}

print(first-second)

# 差集。first有而second没有的。{2, 3, 4}

print(first ^ second)

# 并集减去交集。{2, 3, 4, 5}

second[0]

# 出错了,不能用索引访问,因为集合是无序的


字典

字典非常重要,它指的是键值对。键值对的使用随处可见,比如当下最流行的json,mongodb,redis等等。

键:只能由字符串 或 数值 构成;

值:可以使用任何类型。

# 有两种创建字典的方法

point = {“x”: 1, “y”: 2}

# 创建方法一

point = dict(x=1, y=2)

# 创建方法二

# 这种方法很不错,python各数据结构都有对应的函数可以创建,

# 比如 list(),tuple(),set(),dict()等

point[“x”] = 10

# 设置值

point[“z”] = 20

# 如果键不存在,将创建新的键值对

point[“a”]

# 出错!不存在就读取会出错。需要先检测是否存在

# 有两种方法检测是否存在

if “a” in point:

    print(point[“a”])

# 或

print(point.get(“a”, 0))

print(point.get(“a”, None))

# 用get获取,不存在返回0,或返回None等

del point[“x”]

# 删除键值对

for key in point:

    print(key)

# 默认遍历的是键

# 可以用拆包方式读取键和值

for key, value in point.items():

    print(key, value)

# 或更简单的方法

for key in point:

    print(key, point[key])


字典推导

类似列表推导:

将中括号改成大括号,变成set推导;

在set中加入键和冒号则可以变成字典。

values = {x: x*2 for x in range(5)}

print(values)

# 输出 {0: 0, 1: 2, 2: 4, 3: 6, 4: 8}

values = {x*2 for x in range(5)}

print(values)

# 输出 {0, 2, 4, 6, 8}


生成器表达式

列表推导非常好用,但如果生成的数量太多,内存要占用大量数据,影响性能,可以用生成器表达式,避免过多占用内存。

from sys import getsizeof

values = (x*2 for x in range(100000))

# 注意这里是将列表推导的中括号变成了小括号

# 小括号表示生成器表达式,这样不会在内存中生成全部数据

print(“gen:”, getsizeof(values))

# 在我的电脑中输出 gen: 112

# 只有112个数值占用内存

# 同样的,如果我们用常规的中括号

values = [x*2 for x in range(100000)]

print(“List:”, getsizeof(values))

# 在我的电脑中输出是 List: 800984,全部数据都占用了内存

生成器表达式由于事先不知道会有多少项,所以不能使用len函数。

len(values)

# 提示错误!


拆包操作符

一个星号 * :拆分迭代,可拆任何迭代的东西

二个星号 ** : 拆分字典

现代语言或更新版的传统语言一般都加进了拆包功能,如javascript es6版就添加了拆包功能

numbers = [1, 2, 3]

print(numbers)

# 输出[1, 2, 3]

print(*numbers)

# 拆分输出3个数 1 2 3

创建列表时使用拆包

values = list(range(5))

values = [*range(5)]

# 上面两行代码是等同的,一个是常规方法,另一个用了拆包技术

合并列表也非常有用

first = [1, 2]

second = [3]

values = [*first, “a”, *second, *”Hello”]

print(values)

# 输出 [1, 2, ‘a’, 3, ‘H’, ‘e’, ‘l’, ‘l’, ‘o’]

拆包字典,使用双星号 **

first = {“x”: 1}

second = {“x”: 10, “y”: 2}

combined = {**first, **second, “z”: 1}

print(combined)

# 输出 {‘x’: 10, ‘y’: 2, ‘z’: 1}

# 注意有两个键 “x”,以后一个为准


异常

看下基础结构

try:

    age = int(input(“Age: “))

except ValueError as ex:

    # ex是别名

    print(“You didn’t enter a valid age.”)

    print(ex)

    print(type(ex))

else:

    # else也可以省略

    print(“No exceptions were thrown.”)

处理不同的异常

try:

    age = int(input(“Age: “))

    afactor = 10/age

except (ValueError, ZeroDivisionError):

    # 捕捉多个异常

    print(“You didn’t enter a valid age.”)

else:

    print(“No exceptions were thrown.”)

清理

在使用外部资源时,比如打开文件、数据连接、网络连接时,使用后必须关闭掉,如果使用过程发生错误,将不会关闭导致其他程序无法使用,所以需要进行清理。

try:

    file=open(“app.py”)

    …

except(ValueError,…):

    …

else:

    …

finally:

    file.close()

    # finally不管有无异常都将执行,关闭外部资源一般放在这里

with语句

可以不用finally显式地清理或释放外部资源,python的with语句可以做到自动释放。

try:

    with open(“app.py”) as file:

        # with语句可以自动释放资源,支持with语句的对象都有两个魔术方法:

        # __enter__() 和 __exit()__()

        # 魔术方法会在讲python类时会详细讲解,现在知道就有双下划线开头的方法就好

        print(“File opened.”)

    …

except:

    …

else:

    …

引发异常

有时我们需要主动抛出异常

def calculate_xfactor(age):

    if age <= 0:

        raise ValueError(“Age cannot be 0 or less.”)

        # raise 抛出异常

    return 10/age

try:

    calculate_xfactor(-1)

except ValueError as error:

    print(error)

    # 显示我们自定义的提示信息 Age cannot be 0 or less.

抛出异常的成本

抛出异常会增加开销,如果代码中可以不用抛出异常的方法处理,就尽量不抛。我们比较下差别。

from timeit import timeit

code1 = ”’

def calculate_xfactor(age):

    if age <= 0:

        raise ValueError(“Age cannot be 0 or less.”)

    return 10/age

try:

    calculate_xfactor(-1)

except ValueError as error:

    print(error)

”’

code2 = ”’

def calculate_xfactor(age):

    if age <= 0:

        return 0

    return 10/age

if not calculate_xfactor(-1):

    print(“Age cannot be 0 or less.”)

”’

print(timeit(code1, number=10000))

print(timeit(code2, number=10000))

# 分别重复执行code1代码和code2代码 10000次,返回执行时间

# code1代码段就是前面的抛出异常的代码

# code2代码是修改的不抛出异常的解决方法

# 实验结果:code1是0.11秒,code2是0.09,是有些开销差距的。


小结

本文介绍了python中的集合、字典和生成器表达式,以及python的异常处理框架,希望对您有帮助。

下一篇将开始介绍 python类相关知识。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注