Python极简读书笔记(五)Python高级特性

140 阅读2分钟

更高效、更专业的Python代码,涉及面向对象程序设计、迭代器、生成器、文件操作、异常处理、错误调试等。

OOP(Object Oriented Programming)

程序 = 对象 + 消息传递

对象 = 数据 + 方法

类:讲具有相同属性(数据)及相同行为(对数据操作)封装在一起。即对某一类事物的描述,它是抽象的、概念上的定义。

对象:实际存在的该类事务中的个体,因此也被称为实例(instance)

类的定义与使用

class ClassName:
  class_suit

一般来说,方法 和 函数 可以看作同义词。但在python中,方法指与特定实例绑定的函数,也就是类中的函数称为方法。

class Person:
    height = 140 # 类的对象成员
    def __init__(self, name, age, weight):  # 对象的数据成员
        self.name = name
        self.age = age
        self.__weight = weight  # 私有数据成员
    def speak(self):
        print("%s 重 %d kg" % (self.name, self.__weight))
        
p1 = Person('Alice', 10, 30)

Python类的后门

对象可以添加新的临时属性

image-20221102175012898

类的继承

继承已有类的基础上新增自己的特性,继而产生新类的过程,称为派生。

既有的类——基类base class、超类super class、父类parent class

派生的类——派生类derived class、子类sub class

python还支持多继承

  • 问:多继承存在的“菱形继承”风险是什么风险?

    • 可以很清楚的看到,Super类的构造函数被调用了两次,这就会出现问题了,如果 在某些应用场景下,Super的构造函数是一个计数器,那么就会导致错误的结果了。
    • 为了解决这个问题,python中专门引入了MRO顺序来解决这个问题。
      MRO顺序本质上执行的是广度优先搜索,从左到右,搜索完同一层级的时候,向上爬升。
      保证了每个类中的方法只会被执行一次。避免了同一个类被调用多次的情况。
      
    • MRO顺序说人话就是,若基类中有相同的方法名,那么在子类未指定的情况下,则Python将从基类列表中以从左到右的顺序查找是否包含该方法。
class Student(Person):
    grad = ''
    def __init__(self, name, age, weight, grad):
        #调用父类的构造方法,初始化父类数据成员
        Person.__init__(self, name, age, weight)
        self.grad = grad

image-20221104113941380

生成器(generator)与迭代器(iterator)

  • 生成器:

    • 不必生成完整的列表、字典或集合,因为局部性原理,不需要把所有的元素加载到内存中。这种一边循环一边计算的机制,称为生成器。

    • 生成器的定义(1)

      image-20221104115321613

n = 10
a = [i**2 for i in range(n) if i % 2 == 0]
print(a)
b = (i**2 for i in range(n) if i % 2 == 0)
print(b)
type(a)
type(b)
​
[0, 4, 16, 36, 64]
<generator object <genexpr> at 0x7fdc04bcd6d0>
list
generator

image-20221104115646724

  • yield创建生成器

    • fibonacci.py

      • def fibonacci(xterms):
            n, a, b = 0, 0, 1
            while n < xterms:
                print(b, end = ' ')
                a, b = b, a + b
                n = n + 1
            return '输出完毕'
        ​
        fibonacci(10)
        
    • yield改造后

      • def fibonacci(xterms):
            n, a, b = 0, 0, 1
            while n < xterms:
                yield(b)
                a, b = b, a + b
                n = n + 1
            return '输出完毕'
        ​
        fibonacci(10)
        

        image-20221104120528882

迭代器

列表、元组、字典、集合、字符串等容器container,逐个访问其中的元素的过程就是迭代 iteration

my_list = [1,2,3,4]
it = iter(my_list)
•
while True:
    try:
        print(next(it))
    except StopIteration:
        print("迭代器越界了")
        break
print("我能正常输出")
​
1
2
3
4
迭代器越界了
我能正常输出

image-20221104152147739

创建迭代器

所有迭代器在设计之时通常都会在类中实现两个方法:--iter--() 和 --next--()。前者用于返回一个迭代器对象,后者用于返回迭代对象内部的下一个元素值。

from itertools import islice
class Fibonacci:
    def __init__(self):
        self.previous, self.current = 0, 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        value = self.current
        self.previous, self.current = self.current, self.current + self.previous
        return value
    
f = Fibonacci()
a = list(islice(f, 0, 10))
print(a)

image-20221104152719898

image-20221104152739370

文件操作

file = open('filename.txt', mode = 'r') # 打开文件

image-20221104155413056

for line in file:
		print(line) # 按行打印
		
print(file.read()) # 全部打印
fileObject.seek(offset[, whence])

image-20221107151828823

f.read() # 一次性读入,以字节为单位
f.readline() # 一次读入一行
lines = f.readlines() # 一次性读入,以行为单位
lines[:2] # 返回文件前两行
f.close() # 关闭文件

IOError:

  • try-finally
try:
		fhand = open('python.txt', 'r')
		print(fhand.read())
finally:
		if fhand: 
				fhand.close()
  • with语句
with open('python.txt', 'r') as f:
		print(f.read())

写入文件

# 'w'/'wb'写文本文件/写二进制文件

write()方法只能用于向文件中写入指定字符串,在文件关闭或缓冲区刷新前,文件中看不到写入内容。

f.write(123) # 会报错
f.write(str(134)) # 可以

异常处理

image-20221107172847725

错误调试

  • print

  • assert断言

    • 但凡能用print的,都能用assert代替
    assert <condition>, "arguments"
    
    等价于
    
    if not <condition>:
    		raise AssertionError(arguments)
    

    image-20221107175433900

    -O参数可以关闭assert

    python -O assert_no_err_msg.py