前言
昨天被人问道:“你知道装饰器吗?你知道python的上下文管理器吗?(使用with语句操作上下文管理器类)”
简单日记程序
写过日记的小伙伴都知道,写日记的时候首先会写日期,然后去写正文。那现在都已经21世纪了,是不是可以考虑做一个日记程序呢?
程序员的最终目的:把更多的事情交给程序去做。
第一步,自定义上下文管理器类 - OpSqliteDB
为了过滤掉复杂冗余的步骤,我选择使用轻量级的关系型数据库:sqlite3
为了保持文件结构清晰,我在utils.py文件中实现了一个操作sqlite3的函数opSqlite
diary/utils.py
import sqlite3
def opSqlite(dbName='default.db', sql=None):
conn = sqlite3.connect(dbName)
if sql:
cursor = conn.cursor()
cursor.execute(sql)
conn.commit()
conn.close()
其次我在createDiaryDB.py中单独创建需要的表结构,代码如下
diary/createDiaryDB.py
from utils import opSqlite
sql = """
CREATE TABLE diary(
diary_datetime TEXT,
content TEXT NOT NULL
)
"""
opSqlite('diary.db', sql)
操作数据库也是一种对资源的操作,数据库的连接和关闭是对资源的管理。
当我做完这两步之后,我想到可以自定义一个OpSqliteDB
上下文管理器类,使用with语句帮助我管理数据库的连接和关闭。
于是我把diary/utils.py中的代码改成了上下文管理器类OpSqliteDB
:
import sqlite3
"""
def opSqlite(dbName='default.db', sql=None):
conn = sqlite3.connect(dbName)
if sql:
cursor = conn.cursor()
cursor.execute(sql)
conn.commit()
conn.close()
"""
class OpSqliteDB:
def __init__(self, dbName):
self.dbName = dbName
self.conn = None
self.cursor = None
def __enter__(self):
# conncet sqlite db
print('--- open sqlite db ---')
self.conn = sqlite3.connect(self.dbName)
self.cursor = self.conn.cursor()
print('--- return db cursor ---')
return self.cursor
def __exit__(self, exc_value, exc_type, exc_tb):
print('--- commit result ---')
self.conn.commit()
print('--- close sqlite db ---')
self.conn.close()
同时把diary/createDiaryDB.py中的代码用with语句操作:
from utils import OpSqliteDB
sql = """
CREATE TABLE diary(
diary_datetime TEXT,
content TEXT NOT NULL
)
"""
# opSqlite('diary.db', sql)
with OpSqliteDB('diary.db') as cursor:
cursor.execute(sql)
其执行结果如下图,可以看到通过with执行我自定义的上下文管理器类OpSliteDB
实现了对数据库的连接、关闭的管理。
其实代码写到现在,似乎有一个很模糊的问题缠绕着自己,就是为什么要自定义上下文管理器类呢?
理由:
1.具体的应用场景:用于系统的资源管理,资源的分配与释放。
2.非功能性理由:要培养一个技术人该有的专业素养。具体的问题可能有很多种解决方式,应该用一种最合适的方式解决当前面临的问题
第二步,实现日记功能
基于面向对象的程序设计思想,我创建类一个日记类Diary
,用来实现日记功能:
diary/Diary.py
from utils import OpSqliteDB
class Diary:
def __init__(self, dbName='diary.db', tableName='diary'):
self.dbName = dbName
self.tableName = tableName
self.condition = 'diary_datetime', 'content'
def write(self, diaryRecord):
sql = """
INSERT INTO {} ({},{}) VALUES ('{}','{}')
""".format(self.tableName, self.condition[0], self.condition[1], diaryRecord[0], diaryRecord[1])
print(sql)
with OpSqliteDB(self.dbName) as cursor:
cursor.execute(sql)
def all_diary(self):
sql = """
SELECT * FROM {}
""".format(self.tableName)
print(sql)
res = tuple()
with OpSqliteDB(self.dbName) as cursor:
cursor.execute(sql)
res = cursor.fetchall()
return res
然后在views.py中实现写日记的逻辑代码:
diary/views.py
from Diary import Diary
from datetime import datetime
def diary():
diary = Diary()
# wirte content
content = input('请输入日记内容:')
# diary_datetime
diary_datetime = datetime.now().date()
diary.write((diary_datetime, content))
res = diary.all_diary()
for r in res:
print(r)
if __name__ == '__main__':
diary()
运行之后的结果如下图:
第三部,用装饰器做点什么?
更新中。。。