第5章 编程范式考察点
面向对象基础及 Python类常考问题
什么是面向对象编程?
Object Oriented Programming(OOP)
◆把对象作为基本单元,把对象抽象成类(Class),包含成员和方法
◆数据封装、继承、多态
◆ Python中使用类来实现。过程式编程(函数),OOP(类)
Python中如何创建类?
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182240175-217439299.png)
成员|方法|私有属性|魔术方法
组合与继承
优先使用组合而非继承
◆组合是使用其他的类实例作为自己的一个属性(Has-a关系)
◆子类继承父类的属性和方法(is a关系)
◆优先使用组合保持代码简单
之前实现 stack/queue 就使用到了组合
类变量和实例变量的区别
区分类变量和实例变量
◆类变量由所有实例共享
◆实例变量由实例单独享有,不同实例之间不影响
◆当我们需要在一个类的不同实例之间共享变量的时候使用类变量
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182240502-365642475.png)
classmethod/staticmethod区别
classmethod vs staticmethod
◆ 都可以通过 Class.method()的方式使用
◆ classmethod 第一个参数是cls,可以引用类变量
◆ staticmethod 使用起来和普通函数一样,只不过放在类里去组织
class Person:
Country = 'China'
def __init__(self, name):
self.name = name
@classmethod
def print_country(cls):
print(cls.Country)
@staticmethod
def join_name(first_name, last_name):
return last_name + first_name
p1=Person
p1.print_country()
print(p1.join_name('yule', 'wen'))
classmethod是为了使用类变量
staticmethod是代码组织的需要,完全可以放到类之外
什么是元类?使用场景
元类( Meta Class)是创建类的类
◆元类允许我们控制类的生成,比如修改类的属性等
◆使用type来定义元类
◆元类最常见的一个使用场景就是ORM框架
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182240801-765742396.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182241113-2021308251.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182241381-2020165547.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182241638-43156186.png)
本章总结
面向对象与 Python类常考题
◆什么是面向对象编程, Python如何使用类
◆组合vs继承;类变量vs实例变量; classmethod vs staticmethod
◆元类的创建和使用
Python装饰器常见考题
什么是装饰器
Decorator
◆ Python中一切皆对象,函数也可以当做参数传递
◆ 装饰器是接受函数作为参数,添加功能后返回一个新函数的函数(类)
◆ Python中通过 @ 使用装饰器
编写一个记录函数耗时的装饰器
import time
def log_time(func):
def _log(*args, **kwargs):
beg = time.time()
res = func(*args, **kwargs)
print(f'use time:{time.time() - beg}')
return res
return _log
@log_time
def mysleep():
time.sleep(2)
mysleep()
如何给装饰器增加参数?
使用类装饰器比较方便实现装饰器参数
import time
class Decorator:
def __init__(self, arg1, arg2):
# print('执行类Decorator的__init__()方法')
self.arg1 = arg1
self.arg2 = arg2
def __call__(self, f):
# print('执行类Decorator的__call__()方法')
def wrap(*args):
beg = time.time()
# print('执行wrap()')
# print('装饰器参数:', self.arg1, self.arg2)
# print('执行' + f.__name__ + '()')
f(*args)
# print(f.__name__ + '()执行完毕')
print(f'use time:{time.time() - beg}')
return wrap
@Decorator('Hello', 'World')
def example(a1, a2, a3):
time.sleep(1)
print('传入example()的参数:', a1, a2, a3)
# print('装饰完毕')
# print('准备调用example()')
example('Wish', 'Happy', 'EveryDay')
# print('测试代码执行完毕')
创建型模式常考题
常见创建型设计模式
◆工厂模式( Factory):解决对象创建问题
◆构造模式( Builder):控制复杂对象的创建
◆原型模式( Prototype):通过原型的克隆创建新的实例
◆单例(Borg/ Singleton): 一个类只能创建同一个对象
◆对象池模式(Pool):预先分配同一类型的一组实例
◆惰性计算模式( Lazy Evaluation):延迟计算( python的 property)
工厂模式
什么是工厂模式( Factory)
◆解决对象创建问题
◆解耦对象的创建和使用
◆包括工厂方法和抽象工厂
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182241861-1598457879.png)
学习设计模式的一个有效的方式是自己尝试写个示例代码来演示它
构造模式
什么是构造模式(Builder)
◆用来控制复杂对象的构造
◆创建和表示分离。比如你要买电脑,工厂模式直接给你需要的电脑
◆但是构造模式允许你自己定义电脑的配置,组装完成后给你
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182242116-1764761738.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182242414-586606865.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182242681-154318371.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182242984-1587944478.png)
原型模式
什么是原型模式(Prototype)
◆通过克隆原型来创建新的实例
◆可以使用相同的原型,通过修改部分属性来创建新的示例
◆用途:对于一些创建实例开销比较高的地方可以用原型模式
单例模式
单例模式的实现有多种方式
◆单例模式:一个类创建出来的对象都是同一个
◆Python的模块其实就是单例的,只会导入一次
◆使用共享同一个实例的方式来创建单例模式
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182243240-888418660.png)
结构型模式常考题
常见结构型设计模式
◆ 装饰器模式(Decorator):无需子类化扩展对象功能
◆ 代理模式(Proxy)把一个对象的操作代理到另一个对象
◆ 适配器模式(Adapter):通过一个间接层适配统一接口
◆ 外观模式( Facade):简化复杂对象的访问问题
◆ 享元模式( Flyweight):通过对象复用(池)改善资源利用,比如连接池
◆ Model-View-Controller(MVC):解耦展示逻辑和业务逻辑
代理模式
什么是代理模式(Proxy)
◆把一个对象的操作代理到另个一对象
◆这里又要提到我们之前实现的 Stack/Queue,把操作代理到 deque
◆通常使用has-a组合关系
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182243444-305194768.png)
适配器模式
什么是适配器模式(Adapter)
◆把不同对象的接口适配到同一个接口
◆想象一个多功能充电头,可以给不同的电器充电,充当了适配器
◆当我们需要给不同的对象统一接口的时候可以使用适配器模式
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182243689-2035660363.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182243927-1178125495.png)
请你尝试使用适配器模式完成充电头的例子
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182244175-951666366.png)
行为型模式常考题
常见学习行为型设计模式
◆迭代器模式 (Iterator):通过统一的接口迭代对象
◆观察者模式(Observer):对象发生改变的时候,观察者执行相应动作
◆策略模式(Strategy):针对不同规模输入使用不同的策略
迭代器模式
迭代器模式( Iterator)
◆ Python内置对迭代器模式的支持
◆ 比如我们可以用for遍历各种 Iterable的数据类型
◆ Python里可以实现_next和_iter_实现迭代器
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182244452-987686314.png)
观察者模式
观察者模式
◆发布订阅是一种最常用的实现方式
◆发布订阅用于解耦逻辑
◆可以通过回调等方式实现,当发生事件时,调用相应的回调函数
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182244719-1970125186.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182244988-1354570885.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182245318-1647931773.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182245558-1982894892.png)
策略模式
策略模式( Strategy)
◆根据不同的输入采用不同的策略
◆比如买东西超过10个打八折,超过20个打七折
◆对外暴露统一的接口,内部采用不同的策略计算
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182245814-1726390262.png)
![](https://img2020.cnblogs.com/blog/1165731/202102/1165731-20210221182246042-660213071.png)
Python函数式编程常考题
函数式编程
Python支持部分函数式编程特性
◆ 把电脑的运算视作数学上的函数计算(lambda演算)
◆ 高阶函数:map/reduce/filter
◆ 无副作用,相同的参数调用始终产生同样的结果
In [1]: map?
Init signature: map(self, /, *args, **kwargs)
Docstring:
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
Type: type
Subclasses:
In [2]: map(lambda x:x*2,range(10))
Out[2]: <map at 0x7f40889083d0>
In [3]: list(map(lambda x:x*2,range(10)))
Out[3]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
推荐列表推导代替map
In [4]: [i*2 for i in range(10)]
Out[4]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
In [6]: filter?
Init signature: filter(self, /, *args, **kwargs)
Docstring:
filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
Type: type
Subclasses:
In [7]: list(filter(lambda x:x%2==0,range(10)))
Out[7]: [0, 2, 4, 6, 8]
In [8]: [i for i in range(10) if i%2==0]
Out[8]: [0, 2, 4, 6, 8]
什么是闭包?
Closure
◆绑定了外部作用域的变量的函数
◆即使程序离开外部作用域,如果闭包仍然可见,绑定变量不会销毁
◆每次运行外部函数都会重新创建闭包
from functools import wraps
def cache(func):
store = {}
@wraps(func)
def _(n): # 闭包
if n in store:
return store[n]
else:
res = func(n)
store[n] = res
return res
return _
@cache
def f(n):
if n <= 1:
return 1
return f(n - 1) + f(n - 2)
print(f(10)) #89
闭包:引用了外部自由变量的函数
自由变量:不在当前函数定义的变量
特性:自由变量会和闭包函数同时存在
本文来自博客园,作者:前海渔文乐,转载请注明原文链接:https://www.cnblogs.com/yuleicoder/p/14426693.html