适配器模式(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)
Out[19]:
现在想要对于上面的装饰器做一下功能增强,把一些必要的参数传递给装饰器函数,以增加装饰器函数的灵活性,比如说,对于加法函数,可以传入'+++++'作为参数传入,相应的减法函数传入‘----’,乘法函数传入‘**’,除法函数传入'/////'。
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)
Out[11]:
In [12]:
sub(3,2)
Out[12]:
装饰器的内容都是很套路的函数操作,一般情况下就是用语简化重复代码:即“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语言不是本次培训的内容之一,大家可以查看相应的网上资源,掌握一般的内容还是很容易的。