今日内容
- 上节作业
- 单例模式
class Foo:
pass
obj1 = Foo()#实例,对象
obj2 = Foo()#实例,对象
- 日志模块(logging)
- 程序的目录结构
内容回顾 & 作业
1.字符串格式化
msg = '我是%s,年龄%s'%('alex',19,)
msg = '我是%(name)s,年龄%(age)s'% {'name':'alex','age':'19'}
print(msg)
v1 = '我是{0},年龄{1}'.format('alex',19)
v1 = '我是{0},年龄{1}'.format(*('alex',19,))
v2 = '我是{name},年龄{age}'.format(name='alex',age=19)
v2 = '我是{name},年龄{age}'.format(**{'name':'alex','age':19})
print(v1)
print(v2)
2.有序字典
from collections import OrderedDict
info = OrderedDict()
info['k1'] = 123 #__setitem__
info['k2'] = 456
print(info['k1'])#__getitem__
print(info.keys())
print(info.values())
print(info.items())
3.作业
3.1栈和队列
class Stack(object):
pass
class Queue(object):
pass
3.2反射
class Cloud(object):
def xxx(self):
pass
def upload(self):
pass
def download(self):
pass
def run(self):
#up|C:/xx/xx.zip
#down|xxx.py
value = input('请用户输入要干什么?')
action = value.split('|')[0]
#最low的形式
if action == 'up':
self.upload()
elif action == 'down':
self.download
else:
print('输入错误')
#构造字典
method_dict = {'up':self.upload,'down':self.download}
method = method_dict.get(action)
method()
#反射()
method = getattr(self,action) #upload #self.upload
method()
补充:反射性能
class Foo(object):
def get(self):
pass
obj = Foo()
# if hasattr(obj,'post'): #性能较差
# getattr(obj,'post')
v1 = getattr(obj,'post',None) #推荐
print(None)
3.3循环过程中删除元素:pass
1、请使用面向对象实现栈(后进先出)
2、请是用面向对象实现队列(先进先出)
3、如何实现一个可迭代对象?
4、看代码写结果
class Foo(object):
def __init__(self):
self.name = '武沛齐'
self.age = 100
obj = Foo()
setattr(Foo, 'email', 'wupeiqi@xx.com')
v1 = getattr(obj, 'email')
v2 = getattr(Foo, 'email')
print(v1, v2)
5、请补充代码(提:循环的列表过程中如果删除列表元素,会影响后续的循环,推荐:可以尝试从后向前找)
li = ['李杰','女神','金鑫','武沛齐']
name = input('请输入要删除的姓氏:') # 如输入“李”,则删除所有姓李的人。
请补充代码
###
li = ['李杰','女神','金鑫','武沛齐']
li = ['李杰','李女神','金鑫','武沛齐']
# name = input('请输入要删除的姓氏:')
for i in range(len(li)-1,-1,-1):
if li[i].startswith('李'):
del li[i]
print(li)
6、有如下字典,请删除指定数据。
class User(object):
def init(self, name, age):
self.name = name
self.age = age
info = [User('武沛齐',19),User('李杰',73),User('景女神',16)]
name = input('请输入要删除的用户姓名:')
请补充代码将指定用户对象再info列表中删除。
7、补充代码实现:校园管理系统。
!/usr/bin/env python
-- coding:utf-8 --
class User(object):
def __init__(self, name, email, age):
self.name = name
self.email = email
self.age = age
def __str__(self):
return self.name
class School(object):
"""学校"""
def __init__(self):
# 员工字典,格式为:{"销售部": [用户对象,用户对象,] }
self.user_dict = {}
def invite(self, department, user_object):
"""
招聘,到用户信息之后,将用户按照指定结构添加到 user_dict结构中。
:param department: 部门名称,字符串类型。
:param user_object: 用户对象,包含用户信息。
:return:
"""
pass
def dimission(self, username, department=None):
"""
离职,讲用户在员工字典中移除。
:param username: 员工姓名
:param department: 部门名称,如果未指定部门名称,则遍历找到所有员工信息,并将在员工字典中移除。
:return:
"""
pass
def run(self):
"""
主程序
:return:
"""
pass
if name == 'main':
obj = School()
obj.run()
请编写网站实现如下功能。
需求:
实现 MIDDLEWARE_CLASSES 中的所有类,并约束每个类中必须有process方法。
用户访问时,使用importlib和反射 让 MIDDLEWARE_CLASSES 中的每个类对 login、logout、index 方法的返回值进行包装,最终让用户看到包装后的结果。
如:
用户访问 : http://127.0.0.1:8000/login/ ,
页面显示: 【csrf】【auth】【session】 登录 【session】 【auth】 【csrf】
用户访问 : http://127.0.0.1:8000/index/ ,
页面显示: 【csrf】【auth】【session】 首页 【session】 【auth】 【csrf】
即:每个类都是对view中返回返回值的内容进行包装。
MIDDLEWARE_CLASSES = [
'utils.session.SessionMiddleware',
'utils.auth.AuthMiddleware',
'utils.csrf.CrsfMiddleware',
]
from wsgiref.simple_server import make_server
class View(object):
def login(self):
return '登陆'
def logout(self):
return '等处'
def index(self):
return '首页'
def func(environ,start_response):
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
obj = View()
method_name = environ.get('PATH_INFO').strip('/')
if not hasattr(obj,method_name):
return ["".encode("utf-8"),]
response = getattr(obj,method_name)()
return [response.encode("utf-8") ]
server = make_server('127.0.0.1', 8000,func)
server.serve_forever()
#####
MIDDLEWARE_CLASSES = [
'utils.session.SessionMiddleware',
'utils.auth.AuthMiddleware',
'utils.csrf.CrsfMiddleware',
]
from wsgiref.simple_server import make_server
class View(object):
def login(self):
return '登陆'
def logout(self):
return '等处'
def index(self):
return '首页'
def func(environ,start_response):
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
obj = View()
method_name = environ.get('PATH_INFO').strip('/')
print(method_name)
if not hasattr(obj,method_name):
return ["".encode("utf-8"),]
response = getattr(obj,method_name)()
#对字符串的前后进行包装
# msg = "【auth】【session】 %s 【session】【auth】"%response
import importlib
for path in MIDDLEWARE_CLASSES:
module_path,cls_name = path.rsplit('.',maxsplit=1) # 'utils.session.SessionMiddleware'
module = importlib.import_module(module_path)#from utils import session
cls = getattr(module,cls_name)
obj = cls()
response = obj.process(response)
return [response.encode("utf-8") ]
server = make_server('127.0.0.1', 8000,func)
server.serve_forever()
###
class AuthMiddleware(object):
def process(self,data):
msg = '【auth】 %s 【auth】' % data
return msg
###
class CsrfMiddleware(object):
def process(self,data):
msg = '【csrf】 %s 【csrf】' % data
return msg
###
class SessionMiddleware(object):
def process(self,data):
msg = '【session】 %s 【session】'%data
return msg
内容详细
1.单例模式(23种设计模式)
无论实例化多少次,永远用的都是第一次实例化出来的对象
class Foo:
pass
#多例,没实例化一次就创建一个新的对象
obj1 = Foo() #实例,对象
obj2 = Foo() #实例,对象
print(obj1,obj2)
#单例,无论实例化多少次,都用第一次创建的那个对象
class Foo:
instance = None
def __new__(cls, *args, **kwargs):
#if Foo.instance:
# return Foo.instance
#Foo.instance = object.__new__(cls)
#return Foo.instance
if not Foo.instance:
Foo.instance = object.__new__(cls)
return Foo.instance
obj1 = Foo()
obj2 = Foo()
print(obj1,obj2)
单例模式标准
class Singleton(object):
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = object.__new__(cls)
return cls.instance
obj1 = Singleton()
obj2 = Singleton()
#不是最终,加锁。
文件的连接池
class FileHelper(object):
instance = None
def __init__(self.path):
self.file_object = open(path,mode='r',encoding='utf-8')
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = object.__new__(cls)
return cls.instance
obj1 = FileHelper('x')
obj2 = FileHelper('x')
obj1.file_object.read(1)
obj2.file_object.read(1)
2.模块导入
- 多次导入重新加载
import jd #第一次加载:会加载一遍jd种所有的内容
import jd #由已经加载过,就不再加载
print(456)
import importlib
import jd
importlib.reload(jd)
print(456)
通过模块导入的特性也可以实现单例模式:
#jd.py
class Foo(object):
pass
obj = Foo()
#app.py
import jd #加载jd.py,加载最后会实例化一个Foo对象并赋值给obj
print(jd.obj)
3.日志(模块logging)
- 基本应用
- 日志处理本质:logger/FileHandler/Formatter
- 推荐处理日志方式
import logging
file_handler = logging.FileHandler(filename='x1.log',mode='a',encoding='utf-8')
logging.basicConfig(
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers = [file_handler,],
level=logging.ERROR
)
logging.error('你好')
- 推荐处理日志方式 + 分割
import logging
import time
from logging import handlers
# file_handler = logging.FileHandler(filename='x1.log',mode='a',encoding='utf-8')
file_handler = handlers.TimedRotatingFileHandler(filename='x3', when='s', interval=5, encoding='utf-8')
logging.basicConfig(
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers = [file_handler,],
level=logging.ERROR
)
for i in range(1,100000):
time.sleep(1)
logging.error('你好')
3.1快速使用
import logging
logging.basicConfig(
filename='cmdb.log',
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
logging.debug('1')
logging.info('2')
logging.info('3')
logging.warning('4')
logging.error('4')
logging.critical('5')
特殊情况:
import logging
logging.basicConfig(
filename='cmdb1.log',
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
#无效
logging.basicConfig(
filename='cmdb2.log',
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
logging.critical('5')
注意事项:
#在应用日志时,如果想要保留异常的堆栈信息
import logging
import requests
logging.basicConfig(
filename='wf.log',
format='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
try:
requests.get('http://www.xxx.com')
except Exception as e:
msg = str(e) #调用e.__str__方法
logging.error(msg,exc_info=True)
4.项目结构目录
- 脚本
- 单可执行文件
- 多可执行文件