更高效、更专业的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类的后门
对象可以添加新的临时属性
类的继承
继承已有类的基础上新增自己的特性,继而产生新类的过程,称为派生。
既有的类——基类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
生成器(generator)与迭代器(iterator)
-
生成器:
-
不必生成完整的列表、字典或集合,因为局部性原理,不需要把所有的元素加载到内存中。这种一边循环一边计算的机制,称为生成器。
-
生成器的定义(1)
-
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
-
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)
-
-
迭代器
列表、元组、字典、集合、字符串等容器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
迭代器越界了
我能正常输出
创建迭代器
所有迭代器在设计之时通常都会在类中实现两个方法:--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)
文件操作
file = open('filename.txt', mode = 'r') # 打开文件
for line in file:
print(line) # 按行打印
print(file.read()) # 全部打印
fileObject.seek(offset[, whence])
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)) # 可以
异常处理
错误调试
-
print
-
assert断言
- 但凡能用print的,都能用assert代替
assert <condition>, "arguments" 等价于 if not <condition>: raise AssertionError(arguments)-O参数可以关闭assert
python -O assert_no_err_msg.py