第5章 编程范式考察点

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

什么是面向对象编程?
Object Oriented Programming(OOP)
把对象作为基本单元, 把对象抽象成类(class) 包含成员和方法
数据封装, 继承, 多态

? Py中使用类来实现, 过程式编程(函数), OOP(类)

Py中如何创建类?

class Person(object):   #py3 直接class Person
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_name(self):
        print('my name is {}'.format(self.name))

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

组合与继承
优先使用组合而非继承
组合是使用其他的类实例作为自己的一个属性(Has-a 关系)

? 子类继承父类的属性和方法(is a 关系)

? 优先使用组合保持代码简单

? 之前实现栈/队列使用组合

类变量和实例变量的区别
区分类变量和实例变量
类变量由所有实例共享

? 实例变量由实例单独享有, 不同实例之间不影响

? 当我们需要一个类的不同实例之间共享变量的时候使用类变量

class Person:

    Country = 'china'   #类变量

    def __init__(self, name):
        self.name = name #实例属性/变量

    def print_name(self):
        print(self.name)

laowang = Person('laowang')
laoli = Person('laoli')
laoli.print_name()
print(laowang.Country)
print(laoli.Country)

classmethod/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   #last_name  

什么是元类? 使用场景
元类(Meta Class)是创建类的类
元类允许我们控制类的生成, 比如修改类的属性等

? 使用type来定义元类

? 元类最常见的一个使用场景就是ORM框架

__new__     生成实例
__init__    初始化

总结
什么是面向对象?py如何使用类

? 组合vs继承 类变量vs实例变量 classmethod vs staticmethod

? 元类的创建和使用

py装饰器常见考题

什么是装饰器
Decorator
py中一切皆对象, 函数也可以当做参数传递
装饰器是接受函数作为参数, 添加功能后返回一个新函数的函数(类)
py中通过@使用装饰器

编写一个记录函数耗时的装饰器

import time

def log_time(func): #接受一个函数作为参数
    def _log(*args, **kwargs):
        beg = time.time()
        res = func(*args, **kwargs)
        print('use time: {}'.format(time.time()-beg))
        return res
    return _log

@log_time   #@装饰器语法糖
def mysleep():
    time.sleep(1)

newsleep = log_time(mysleep)
newsleep()

如何使用类编写装饰器

import time
class LogTime:

    def __call__(self, func):
        def _log(*args, **kwargs):
            beg = time.time()
            res = func(*args, **kwargs)
            print('use time: {}'.format(time.time()-beg))
        return _log

@LogTime()
def mysleep2():
    time.sleep(1)

mysleep2()

如何给装饰器增加参数?
使用类装饰器比较方便实现装饰器参数

class LogTimeParams:

def __init__(self, use_int=False):
    self.use_int = use_int

def __call__(self, func):
    def _log(*args, **kwargs):
        beg = time.time()
        res = func(*args, **kwargs)
        if self.use_int:
            print('use time: {}'.format(int(time.time()-beg)))
        else:
            print('use time: {}'.format(time.time()-beg))
        return res
    return _log

设计模式:
创建型,结构型,行为型 23种设计模式
创建型模式 py应用面试题

常见创建型设计模式

  • 工厂模式(Factory):解决对象创建问题
  • 构造模式(Buider): 控制复杂对象的创建
  • 原型模式(Prototype):通过原型的克隆创建新的实例
  • 单例(Borg/Singleton): 一个类只能创建同一个对象
  • 对象池模式(Pool):预先分配同一类型的一组实例
  • 惰性计算模式(Lazy Evaluation): 延迟计算(py中的property)

工厂模式
什么是工厂模式(Factory)

  • 解决对象创建问题 解耦对象的创建和使用 包括工厂方法和抽象工厂

class DogToy:
    def speak(self):
        print("wang wang")

class CatToy:
    def speak(self):
        print("miao miao")

def toy_factory(toy_type):
    if toy_type == 'dog':
        return DogToy()
    elif toy_type == 'cat':
        return CatToy()

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

class Computer:
    def __init__(self, serial_number):
        self.serial = serial_number
        self.memory = None      #in gigabytes
        self.hdd = None
        self.gpu = None

    def __str__(self):
        info = ('Memory: {}GB'.format(self.memory),
                'Hard Disk: {}GB'.format(self.hdd),
                'Graphics Card: {}'.format(self.gpu))
        return '\n'.join(info)

class ComputerBuilder:
    def __init__(self):
        self.computer = Computer('AG23385193')

    def configure_memory(self, amount):
        self.computer.memory = amount

    def configure_hdd(self, amount):
        self.computer.hdd = amount

    def configure_gpu(self, gpu_model):
        self.computer.gpu = gpu_model

class HardwareEngineer:
    def __init__(self):
        self.builder = None

    def construct_computer(self, memory, hdd, gpu):
        self.builder = ComputerBuilder()
        [step for step in (self.builder.configure_memory(memory),
                           self.builder.configure_hdd(hdd),
                           self.builder.configure_gpu(gpu))]

    @property
    def computer(self):
        return self.builder.computer

#use builder create 多个builder类实现不同的组装方式
engineer = HardwareEngineer()
engineer.construct_computer(hdd=500, memory=8, gpu='geForce GTX 650 Ti')
computer = engineer.computer

print(computer)

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

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

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            _instance = super().__new__(cls, *args, **kwargs)
            cls._instance = _instance
        return cls._instance

class MyClass(Singleton):
    pass

c1 = MyClass()
c2 = MyClass()

assert c1 is c2

print(id(c1))
print(id(c2))
print(c1 is c2)

设计模式:结构型模式python应用面试题

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

什么是代理模式(proxy)
把一个对象的操作代理到另一个对象
之前实现的Stack/Queue, 把操作代理到deque
通常使用has-a组合关系

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

#适配器模式的例子
class Dog(object):
    def __init__(self):
        self.name = "Dog"

    def bark(self):
        return "woof!"

class Cat(object):
    def __init__(self):
        self.name = "Cat"

    def meow(self):
        return "meow!"

class Adapter:
    def __init__(self, obj, **adapted_methods):
        """We set adapted methods in the object's dict"""
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        """All non-adapted calls are passed to the object"""
        return getattr(self.obj, attr)

objects = []
dog = Dog()
objects.append(Adapter(dog, make_noise=dog.bark))
cat = Cat()
objects.append(Adapter(cat, make_noise=cat.meow))
for obj in objects:
    print("A {0} goes {1}".format(obj.name, obj.make_noise()))

设计模式:行为型模式Python应用面试题
行为型模式常考题
常见学习行为型设计模式
迭代器模式(Iterator):通过统一的接口迭代对象
观察者模式(Observer):对象发生改变的时候,观察者执行相应动作
策略模式(Strategy): 针对不同规模输入使用不同的策略
迭代器模式(Iterator)
py内置对迭代器模式的支持

''' 可以用for遍历各种Iterable的数据类型
    py可以实现_next_和_iter_实现迭代器 '''
from collections import deque

class Stack(object):    #使用组合的例子

    def __init__(self):
        self._deque = deque()   #has a deque()

    def push(self, value):
        return self._deque.append(value)

    def pop(self):
        return self._deque.pop()

    def empty(self):
        return len(self._deque) == 0

    def __iter__(self):
        res = []
        for i in self._deque:
            res.append(i)
            for i in reversed(res):
                yield i
s = Stack()
s.push(1)
s.push(2)
for i in s:
    print(i)

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

#发布订阅模式

class Publisher: #发布者
    def __init__(self):
        self.observers = []     #观察者

    def add(self, observer):    #加入观察者
        if observer not in self.observers:
            self.observers.append(observer)
        else:
            print('Failed to add: {}').format(observer)

    def remove(self, observer):     #移除观察者
        try:
            self.observers.remove(observer)
        except ValueError:
            print('Failed to remove: {}').format(observer)

    def notify(self):   #调用观察者的回调
        [o.notify_by(self) for o in self.observers]

class Formatter(Publisher): #继承自发布者
    def __init__(self, name):
        super().__init__()
        self.name = name
        self._data = 0

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, new_value):
        self._data = int(new_value)
        self.notify()   #data 在合法赋值以后会执行notify

class BinaryFormatter:
    """订阅者"""

    def notify_by(self, publisher):
        print("{}: '{}' has now bin data = {}".format(
            type(self).__name__,
            publisher.name,
            bin(publisher.data))
        )

df = Formatter('formatter') #发布者
bf = BinaryFormatter()  #订阅者
df.add(bf)  #添加订阅者
df.data = 3 #设置的时候调用订阅者的notify_by

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

#策略模式
class Order:
    def __init__(self, price, discount_strategy=None):
        self.price = price
        self.discount_startegy = discount_strategy

    def price_after_discount(self):
        if self.discount_startegy:
            discount = self.discount_startegy(self)
        else:
            discount = 0
        return self.price - discount

    def __repr__(self):
        fmt = "<Price: {}, price after discount: {}>"
        return fmt.format(
            self.price, self.price_after_discount()
        )

def ten_percent_discount(order):
    return order.price * 0.25 + 20

def on_sale_discount(order):
    return order.price * 0.25 + 20

def main():
    order0 = Order(100)
    order1 = Order(100, discount_strategy=ten_percent_discount)
    order2 = Order(1000, discount_strategy=on_sale_discount)
    print(order0)
    print(order1)
    print(order2)

main()

py函数式函数式编程
过程式编程,OOP, 简单函数式

py支持部分函数式编程特性
把电脑的运算视作数学上的函数计算(lambda演算)
高阶函数: map/reduce/filter
无副作用, 相同的参数调用始终产生同样的结果

map(lambda x:x*2, range(10))

list(map(lambda x:x*2, range(10)))

[i*2 for i in range(10)]
    推荐列表推导代替map

from functools import reduce

reduce(lambda x,y: x+y, range(1, 6))

filter(lambda x: x % 2 == 0, range(10))

[i for i range(10) if i % 2 == 0]

什么是闭包?
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)

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

原文地址:https://www.cnblogs.com/xuzhaoping/p/11616777.html

时间: 2024-10-22 05:40:01

第5章 编程范式考察点的相关文章

第8章防范式编程上(代码大全3)

防御式编程并不是说让你在编程时持“防备批评或攻击”的态度——“它就是这么工作!”这一概念来自防御式驾驶.在防御式驾驶中要建立这样一种思维,那就是你永远也不能确定另一位司机将要做什么.这样才能确保其他人在做出危险动作时你也不会受到伤害.你要担负起保护自己的责任,哪怕是其他司机犯的错误.防御式编程的主要思想是:子程序应该不因为传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据.更一般地说,其核心是要承认程序都会有问题,都需要被修改,聪明的程序员应该根据这一点来编程序. 8.1 Protectin

第8章防范式编程下(代码大全4)

8.4 Exceptions 异常 用异常通知程序的其他部分,发生了不可忽略的错误 只在真正例外的情况下才抛出异常 不能用异常来推卸责任 避免在构造函数和析构函数中抛出异常,除非你在同一地方把它们捕获 在恰当的抽象层次抛出异常 在异常消息中加入关于导致异常发生的全部信息 避免使用空的catch语句 了解所用函数库可能抛出的异常 考虑创建一个集中的异常报告机制 把项目中对异常的使用标准化 对于像C++这类语言,其中允许抛出多种多样的对象.数据及指针的话,那么就应该为到底可以抛出哪些类的异常建立一个

jQuery中的编程范式

浏览器前端编程的面貌自2005年以来已经发生了深刻的变化,这并不简单的意味着出现了大量功能丰富的基础库,使得我们可以更加方便的编写业务代码,更重要的是我们看待前端技术的观念发生了重大转变,明确意识到了如何以前端特有的方式释放程序员的生产力.本文将结合jQuery源码的实现原理,对javascript中涌现出的编程范式和常用技巧作一简单介绍.    1. AJAX: 状态驻留,异步更新      首先来看一点历史. A. 1995年Netscape公司的Brendan Eich开发了javacri

傻瓜式编程范式,程序员的基本功

我从数据连续性论文延伸阅读时,在HN thread 论坛 @TuringTest 的发言引用中,意外发现了一篇文章<傻瓜式编程范式:程序员基本功>,由彼得·范·罗伊写于 2009 年,描绘了设计编程语言的操作空间.如果你喜欢这篇文章,可能也会喜欢范·罗伊和哈利迪的书<Concepts, Techniques, and Models of Computer Programming>,因为该文的主要内容正是基于这本书. 本文介绍了所有主要编程范式.它们底层的概念以及它们的关系…我们给出

java第四章编程题(初学篇)

代码: 1 /* 2 test.java 3 */ 4 package test; 5 public class test { 6 public static void main(String args[] ) 7 { 8 CPU ccp= new CPU(); 9 HardDisk hhd=new HardDisk(); 10 PC pc =new PC(); 11 ccp.setSpeed(2200); 12 hhd.setAmount(200); 13 pc.setCPU(ccp); 14

java学习之第五章编程题示例(初学篇)

1 /* 2 Animal.java 3 */ 4 package animal; 5 6 public abstract class Animal { 7 public abstract void cry(); 8 public abstract String getanimalName(); 9 } 1 //Dog.java 2 package animal; 3 4 public class Dog extends Animal 5 { 6 7 String aa="旺旺"; 8

编程范式

编程范式(Programming Paradigm)是某种编程语言典型的编程风格或者说是编程方式.随着编程方法学和软件工程研究的深入,特别是OO思想的普及,范式(Paradigm)以及编程范式等术语渐渐出现在人们面前.面向对象编程(OOP)常常被誉为是一种革命性的思想,正因为它不同于其他的各种编程范式.编程范式也许是学习任何一门编程语言时要理解的最重要的术语. 托马斯.库恩提出“科学的革命”的范式论之后,Robert Floyd在1979年图灵奖的颁奖演说中使用了编程范式一词.编程范式一般包括三

c++ primer plus(第6版)中文版 第九章编程练习答案

首先,说明下环境: linux:fedora14: IDE:eclipse: python:python2.7 python框架:django web服务器:apache web服务器的python模块:mod_wsgi 写在前面: 之前用的windows下面的xampp,写的php后台,现在想转向linux下面的python,跟以前一样,选择apache和eclipse作为自己的开发工具. eclipse的python配置, 参见之前的博客:http://blog.csdn.net/zy416

编程范式:响应式编程

响应式编程是一种面向数据流和变化传播的编程范式.这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播. 例如,在命令式编程环境中,a:=b+c表示将表达式的结果赋给a,而之后改变b或c的值不会影响a.但在响应式编程中,a的值会随着b或c的更新而更新. Event buses或者Click events本质上就是异步事件流(Asynchronous event stream),你可以监听并处理这些事件:任何一个东西我们都可以把他们当成一个str