第5章 编程范式考察点

面向对象基础及 Python类常考问题



什么是面向对象编程?

Object Oriented Programming(OOP)
◆把对象作为基本单元,把对象抽象成类(Class),包含成员和方法
◆数据封装、继承、多态
◆ Python中使用类来实现。过程式编程(函数),OOP(类)

Python中如何创建类?

成员|方法|私有属性|魔术方法


组合与继承

优先使用组合而非继承
◆组合是使用其他的类实例作为自己的一个属性(Has-a关系)
◆子类继承父类的属性和方法(is a关系)
◆优先使用组合保持代码简单
之前实现   stack/queue 就使用到了组合

类变量和实例变量的区别

区分类变量和实例变量
◆类变量由所有实例共享
◆实例变量由实例单独享有,不同实例之间不影响
◆当我们需要在一个类的不同实例之间共享变量的时候使用类变量




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框架









本章总结

面向对象与 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)
◆解决对象创建问题
◆解耦对象的创建和使用
◆包括工厂方法和抽象工厂
学习设计模式的一个有效的方式是自己尝试写个示例代码来演示它

构造模式

什么是构造模式(Builder)
◆用来控制复杂对象的构造
◆创建和表示分离。比如你要买电脑,工厂模式直接给你需要的电脑
◆但是构造模式允许你自己定义电脑的配置,组装完成后给你



原型模式

什么是原型模式(Prototype)
◆通过克隆原型来创建新的实例
◆可以使用相同的原型,通过修改部分属性来创建新的示例
◆用途:对于一些创建实例开销比较高的地方可以用原型模式

单例模式

单例模式的实现有多种方式
◆单例模式:一个类创建出来的对象都是同一个
◆Python的模块其实就是单例的,只会导入一次
◆使用共享同一个实例的方式来创建单例模式

结构型模式常考题

常见结构型设计模式

◆ 装饰器模式(Decorator):无需子类化扩展对象功能
◆ 代理模式(Proxy)把一个对象的操作代理到另一个对象
◆ 适配器模式(Adapter):通过一个间接层适配统一接口
◆ 外观模式( Facade):简化复杂对象的访问问题
◆ 享元模式( Flyweight):通过对象复用(池)改善资源利用,比如连接池
◆ Model-View-Controller(MVC):解耦展示逻辑和业务逻辑

代理模式

什么是代理模式(Proxy)
◆把一个对象的操作代理到另个一对象
◆这里又要提到我们之前实现的 Stack/Queue,把操作代理到 deque
◆通常使用has-a组合关系

适配器模式

什么是适配器模式(Adapter)
◆把不同对象的接口适配到同一个接口
◆想象一个多功能充电头,可以给不同的电器充电,充当了适配器
◆当我们需要给不同的对象统一接口的时候可以使用适配器模式



请你尝试使用适配器模式完成充电头的例子

行为型模式常考题

常见学习行为型设计模式

◆迭代器模式 (Iterator):通过统一的接口迭代对象
◆观察者模式(Observer):对象发生改变的时候,观察者执行相应动作
◆策略模式(Strategy):针对不同规模输入使用不同的策略

迭代器模式

迭代器模式( Iterator)
◆ Python内置对迭代器模式的支持
◆ 比如我们可以用for遍历各种 Iterable的数据类型
◆ Python里可以实现_next和_iter_实现迭代器

观察者模式

观察者模式
◆发布订阅是一种最常用的实现方式
◆发布订阅用于解耦逻辑
◆可以通过回调等方式实现,当发生事件时,调用相应的回调函数


策略模式

策略模式( Strategy)
◆根据不同的输入采用不同的策略
◆比如买东西超过10个打八折,超过20个打七折
◆对外暴露统一的接口,内部采用不同的策略计算

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

闭包:引用了外部自由变量的函数
自由变量:不在当前函数定义的变量
特性:自由变量会和闭包函数同时存在

posted @ 2021-02-21 18:16  元贞  阅读(59)  评论(0编辑  收藏  举报