一、实现查找功能的模块
"""
实现查找功能的模块
"""
def seq_search(items, elem):
"""顺序查找"""
for index, item in enumerate(items):
if item == elem:
return index
return -1
def bin_search(items, elem):
"""折半查找(二分查找)"""
start, end = 0, len(items) - 1
while start <= end:
mid = (start + end) // 2
if elem < items[mid]:
end = mid - 1
elif elem > items[mid]:
start = mid + 1
else:
return mid
return -1
二、排序
"""
排序 - 冒泡排序(简单O(N**2)) / 归并排序(高级O(N*log2N))
冒泡排序
34, 99, 52, 11, 47, 68, 50, 84
34, 52, 11, 47, 68, 50, 84, 99
34, 11, 47, 52, 50, 68, 84
11, 34, 47, 50, 52, 68
快速排序
34, 99, 52, 11, 47, 68, 50, 84
{34, 11, 47}, {50}, {99, 52, 68, 84}
{11}, {34}, {47}, {50}, {52, 68, 84}, {99}
{11}, {34}, {47}, {50}, {52}, {68, 84}, {99}
{11}, {34}, {47}, {50}, {52}, {68}, {84}, {99}
归并排序 - 分治法(divide-and-conquer)
34, 99, 52, 11, 47, 68, 50, 84
{34, 99, 52, 11}, {47, 68, 50, 84}
{34, 99}, {52, 11}, {47, 68}, {50, 84}
{34}, {99}, {52}, {11}, {47}, {68}, {50}, {84}
{34, 99}, {11, 52}, {47, 68}, {50, 84}
{11, 34, 52, 99}, {47, 50, 68, 84}
{11, 34, 47, 50, 52, 68, 84, 99}
在使用分治法的时候通常都会使用到递归调用这种编程手段
一个函数直接或间接的调用了自身就称之为递归调用
"""
def bubble_sort(origin_items, *, comp=lambda x, y: x > y):
"""冒泡排序"""
items = origin_items[:]
length = len(items)
for i in range(1, length):
swapped = False
for j in range(0, length - i):
if comp(items[j], items[j + 1]):
items[j], items[j + 1] = items[j + 1], items[j]
swapped = True
if swapped:
swapped = False
for j in range(length - i - 1, i - 1, -1):
if comp(items[j - 1], items[j]):
items[j - 1], items[j] = items[j], items[j - 1]
swapped = True
if not swapped:
break
return items
def merge(list1, list2, comp=lambda x, y: x <= y):
""""有序合并(将两个有序的列表合并成一个新的有序的列表)"""
list3 = []
index1, index2 = 0, 0
while index1 < len(list1) and index2 < len(list2):
if comp(list1[index1], list2[index2]):
list3.append(list1[index1])
index1 += 1
else:
list3.append(list2[index2])
index2 += 1
list3 += list1[index1:]
list3 += list2[index2:]
return list3
def merge_sort(origin_items, comp=lambda x, y: x <= y):
"""归并排序"""
if len(origin_items) <= 1:
return origin_items[:]
mid = len(origin_items) // 2
left = merge_sort(origin_items[:mid], comp)
right = merge_sort(origin_items[mid:], comp)
return merge(left, right, comp)
class Person:
"""人"""
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'{self.name}: {self.age}'
def main():
items = [34, 99, 52, 11, 47, 50, 84]
print(items)
print(merge_sort(items))
if __name__ == '__main__':
main()
三、递归(recursion)
"""
递归(recursion)
"""
def fac(num):
"""求阶乘"""
if num in (0, 1):
return 1
return num * fac(num - 1)
def fib(num, temp={}):
"""计算斐波拉切数"""
if num in (1, 2):
return 1
try:
return temp[num]
except KeyError:
temp[num] = fib(num - 1) + fib(num - 2)
return temp[num]
def fib2(total):
"""斐波拉切数列生成器"""
num1, num2 = 0, 1
for _ in range(total):
num1, num2 = num2, num1 + num2
yield num1
def main():
"""主函数"""
for num in fib2(120):
print(num)
if __name__ == '__main__':
main()
四、设计范式:扑克牌的例子
"""
程序设计的范式(理念):
1. 指令式程序设计 - 汇编语言
2. 面向过程程序设计 - 把一组指令封装成一个过程,需要执行这组指令时调用这个过程即可 - C
3. 面向对象程序设计 - 将数据和操作数据的函数从逻辑上组织成了对象 - C++ / Java
4. 函数式程序设计 - 函数是一等对象(一等公民) - Haskell
面向对象程序设计步骤:
1. 定义类 - 抽象过程 - 数据抽象(静态特征-属性)/行为抽象(动态特征-方法)
2. 创建对象 - 构造器 - 初始化(__init__)
3. 给对象发消息 - 对象引用.对象方法(参数)
面向对象的三大支柱 - 封装 / 继承 / 多态
类与类(对象与对象)之间的关系:
1. is-a: 继承
2. has-a: 关联 / 聚合 / 合成
3. use-a: 依赖
面向对象的设计原则/SOLID原则:
1. 单一职责原则 - 类的设计要高内聚
2. 开闭原则 - 接受扩展不接受修改 - 抽象是关键/用继承封装可变性
3. 依赖倒转原则 - 面向抽象编程
4. 里氏替换原则 - 任何时候都可以使用子类型对象替换父类型对象
5. 接口隔离原则
6. 合成聚合复用原则 - 优先考虑用强关联而不是继承去复用代码
7. 最少知识原则(迪米特法则) - 不要跟陌生人讲话
GoF设计模式 - 23种场景(Python中有16中已经被弱化)
- 单例、工厂、原型、适配器、观察者、策略
"""
from enum import Enum
from enum import unique
import random
@unique
class Suite(Enum):
"""花色"""
SPADE = 0
HEART = 1
CLUB = 2
DIAMOND = 3
class Card():
"""牌"""
def __init__(self, suite, face):
self.suite = suite
self.face = face
def show(self):
"""显示牌的花色和点数"""
suites = ['♠️', '♥️', '♣️', '♦️']
faces = [
'', 'A', '2', '3', '4', '5', '6',
'7', '8', '9', '10', 'J', 'Q', 'K'
]
return f'{suites[self.suite.value]} {faces[self.face]}'
def __str__(self):
return self.show()
def __repr__(self):
return self.show()
class Poker():
"""扑克"""
def __init__(self):
self.index = 0
self.cards = [Card(suite, face)
for suite in Suite
for face in range(1, 14)]
def shuffle(self):
"""洗牌"""
random.shuffle(self.cards)
def deal(self):
"""发牌"""
temp = self.cards[self.index]
self.index += 1
return temp
@property
def has_more(self):
"""是否有牌可以发"""
return self.index < len(self.cards)
class Player():
"""玩家"""
def __init__(self, name):
self.name = name
self.cards = []
def get_one(self, card):
"""摸一张牌"""
self.cards.append(card)
def drop_one(self, index):
"""打出一张牌"""
return self.cards.remove(index)
def get_many(self, more_cards):
"""摸多张牌"""
self.cards += more_cards
def drop_cards(self):
"""扔掉所有牌"""
self.cards.clear()
def arrange(self):
"""整理手上的牌"""
self.cards.sort(key=lambda x: (x.suite.value, x.face))
def main():
"""主函数"""
poker = Poker()
poker.shuffle()
players = [
Player("刘备"), Player("关羽"),
Player("张飞"), Player("曹操")
]
for _ in range(3):
for player in players:
if poker.has_more:
player.get_one(poker.deal())
for player in players:
player.arrange()
print(player.name)
print(player.cards)
if __name__ == '__main__':
main()
五、设计模式-策略模式
"""
设计模式 - 策略模式(指定的策略不同执行的算法不同)
"""
from hashlib import md5
from hashlib import sha1
from hashlib import sha256
from hashlib import sha512
class StreamHasher():
"""哈希摘要生成器"""
def __init__(self, algorithm='md5', size=1024):
self.size = size
alg = algorithm.lower()
if alg == 'md5':
self.hasher = md5()
elif alg == 'sha1':
self.hasher = sha1()
elif alg == 'sha256':
self.hasher = sha256()
elif alg == 'sha512':
self.hasher = sha512()
else:
raise ValueError('不支持指定的摘要算法')
def __call__(self, stream):
return self.to_digest(stream)
def to_digest(self, stream):
"""生成十六进制形式的哈希摘要字符串"""
for data in iter(lambda: stream.read(self.size), b''):
self.hasher.update(data)
return self.hasher.hexdigest()
def main():
"""主函数"""
hasher = StreamHasher('sha1', 4096)
with open('Python魔法方法指南.pdf', 'rb') as stream:
print(hasher(stream))
if __name__ == '__main__':
main()
六、抽象类/继承/多态
"""
抽象类 / 继承 / 多态
"""
from abc import ABCMeta, abstractmethod
class Employee(metaclass=ABCMeta):
"""员工"""
def __init__(self, name):
self.name = name
@abstractmethod
def get_salary(self):
"""结算月薪"""
pass
class Manager(Employee):
"""部门经理"""
def get_salary(self):
return 15000
class Programmer(Employee):
"""程序员"""
def __init__(self, name):
super().__init__(name)
self._working_hour = 0
@property
def working_hour(self):
return self._working_hour
@working_hour.setter
def working_hour(self, _working_hour):
self._working_hour = 0 if _working_hour < 0 \
else _working_hour
def get_salary(self):
return 200 * self.working_hour
class Salesman(Employee):
"""销售员"""
def __init__(self, name):
super().__init__(name)
self._sales = 0
@property
def sales(self):
return self._sales
@sales.setter
def sales(self, _sales):
self._sales = 0 if _sales < 0 else _sales
def get_salary(self):
return 1800 + 0.05 * self.sales
def main():
"""主函数"""
emps = [
Programmer("王大锤"), Manager("武则天"),
Programmer("狄仁杰"), Salesman("白洁"),
Programmer("白元芳"), Salesman("冷面")
]
for emp in emps:
if isinstance(emp, Programmer):
emp.working_hour = int(input(f'{emp.name}本月工作时间: '))
elif isinstance(emp, Salesman):
emp.sales = float(input(f'{emp.name}本月销售额: '))
print("%s本月工资为: ¥%.2f元" % (emp.name, emp.get_salary()))
if __name__ == '__main__':
main()
七、单例模式
"""
设计模式 - 单例模式(让一个类只能创建唯一的实例)
"""
class SingletonMeta(type):
"""单例类的元类(描述其他类的类)"""
def __init__(cls, *args, **kwargs):
cls.__instance = None
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
class President(metaclass=SingletonMeta):
"""总统(单例类)"""
def __init__(self, name):
self.name = name
def main():
p1 = President("王大锤")
p2 = President("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
if __name__ == '__main__':
main()
八、单例模式2
"""
设计模式 - 单例模式(让一个类只能创建唯一的实例)
"""
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class President():
"""总统(单例类)"""
def __init__(self, name):
self.name = name
def main():
p1 = President("王大锤")
p2 = President("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
print('-' * 30)
President2 = President.__wrapped__
p2 = President2("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
if __name__ == '__main__':
main()
九、装饰器
"""
装饰器 - 背后的设计模式是代理模式(注意不是装饰器模式)
代理模式通常是让代理对象去执行被代理对象的行为并在这个过程中增加额外的操作
这种设计模式最适合处理代码中的横切关注功能(与正常业务没有必然联系但是又需要执行的功能)
"""
from functools import wraps
from time import time
def record(*, output=print):
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
output(func.__name__, time() - start)
return result
return wrapper
return decorate
@record()
def some_task():
print(123 ** 100000)
if __name__ == '__main__':
some_task()
print(some_task.__name__)
some_task = some_task.__wrapped__
some_task()
十、作用域
"""
作用域 - Local -> Embedded -> Global -> Built-in
"""
def foo():
x = 300
def bar():
nonlocal x
x = 200
print(x)
bar()
print(x)
if __name__ == '__main__':
foo()