适配器模式(Adapter pattern)是一种结构型设计模式,帮助我们实现两个不兼容接口之间的兼容。

首先,解释一下不兼容接口的真正含义。如果我们希望把一个老组件用于一个新系统中,或者把一个新组件用于一个老系统中,不对代码进行任何修改两者就能够通信的情况很少见。但又并非总是能修改代码,或因为我们无法访问这些代码(例如,组件以外部库的方式提供),或因为修改代码本身就不切实际。在这些情况下,我们可以编写一个额外的代码层,该代码层包含让两个接口之间能够通信需要进行的所有修改。这个代码层就叫适配器。

现在有四个类:


In [13]:
import os


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 Human(object):
    def __init__(self):
        self.name = "Human"

    def speak(self):
        return "'hello'"


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

    def make_noise(self, octane_level):
        return "vroom%s" % ("!" * octane_level)

可能小伙伴们会觉得设计模式这块的东西略微有些复杂,完全不用感到灰心,如果不是想要将软件开发作为自己的职业的话,可能一辈子也不需要了解,或者不经意间用到也不知道。但是这部分内容可以用来复习类的概念知识。

这四个类的的接口各不一样,现在需要实现一个适配器,将这些不同类的接口统一起来:


In [ ]:


In [ ]:


In [ ]:


In [ ]:

回顾一下所掌握的装饰器的知识,现在有以下函数


In [16]:
def add(x, y):
    print('add')
    return x + y

def sub(x, y):
    print('sub')
    return x - y

def mul(x, y):
    print('mul')
    return x * y

def div(x, y):
    print('div')
    return x / y

每次函数都要输出一个print语句告知用户当前在哪个函数中,这样的操作实在是太麻烦,可否实现一个装饰器,自动输出当前所在的函数名称?


In [ ]:


In [ ]:


In [18]:
@debug
def add(x, y):
    return x + y
@debug
def sub(x, y):
    return x - y
@debug
def mul(x, y):
    return x * y
@debug
def div(x, y):
    return x / y

In [19]:
add(3,4)


add
Out[19]:
7

现在想要对于上面的装饰器做一下功能增强,把一些必要的参数传递给装饰器函数,以增加装饰器函数的灵活性,比如说,对于加法函数,可以传入'+++++'作为参数传入,相应的减法函数传入‘----’,乘法函数传入‘**’,除法函数传入'/////'。


In [ ]:


In [10]:
@debug(prefix='++++++')
def add(x, y):
    return x + y
@debug(prefix='------')
def sub(x, y):
    return x - y
@debug(prefix='******')
def mul(x, y):
    return x * y
@debug(prefix='//////')
def div(x, y):
    return x / y

In [11]:
add(3,4)


++++++add
Out[11]:
7

In [12]:
sub(3,2)


------sub
Out[12]:
1

装饰器的内容都是很套路的函数操作,一般情况下就是用语简化重复代码:即“don't repeat yourself‘, 不要写重复的代码。


In [ ]:

SQLite作为一个常见的数据库,也是python的标准库,用途非常广泛,适用于数据量较小的规模,但是又必须使用数据库的场景,sqlite的连接和CRUD操作可以参考标准库的文档。

现在用以下方式创建两个表,然后往里插入一些数据:

-- todo_schema.sql

-- Schema for to-do application examples.

-- Projects are high-level activities made up of tasks create table project ( name text primary key, description text, deadline date );

-- Tasks are steps that can be taken to complete a project create table task ( id integer primary key autoincrement not null, priority integer default 1, details text, status text, deadline date, completed_on date, project text not null references project(name) );

注意,需要将以上sql代码放到一个名为'todo_schema.sql'的文件之中。


In [ ]:
import os
import sqlite3

db_filename = 'todo.db'
schema_filename = 'todo_schema.sql'

db_is_new = not os.path.exists(db_filename)

with sqlite3.connect(db_filename) as conn:
    if db_is_new:
        print('Creating schema')
        with open(schema_filename, 'rt') as f:
            schema = f.read()
        conn.executescript(schema)

        print('Inserting initial data')

        conn.executescript("""
        insert into project (name, description, deadline)
        values ('pymotw', 'Python Module of the Week',
                '2016-11-01');

        insert into task (details, status, deadline, project)
        values ('write about select', 'done', '2016-04-25',
                'pymotw');

        insert into task (details, status, deadline, project)
        values ('write about random', 'waiting', '2016-08-22',
                'pymotw');

        insert into task (details, status, deadline, project)
        values ('write about sqlite3', 'active', '2017-07-31',
                'pymotw');
        """)
    else:
        print('Database exists, assume schema does, too.')

In [ ]:
下面请尝试检索上面所创建数据库中的全部数据:(使用fetchall

In [ ]:


In [ ]:


In [ ]:

当然检索的方式有很多种,fetchall,fetchone,fetchmany都可以实现,如果感兴趣,可以多插入一些数据,然后使用不同的函数进行检索。

数据库的检索一般情况下是程序开发人员需要掌握的必备技能之一,其中检索的操作占据了大部分内容,SQL语言不是本次培训的内容之一,大家可以查看相应的网上资源,掌握一般的内容还是很容易的。