自定义Session
a.知识储备
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class Foo(object):
def __getitem__(self, key):
print '__getitem__',key
def __setitem__(self, key, value):
print '__setitem__',key,value
def __delitem__(self, key):
print '__delitem__',key
obj = Foo()
result = obj['k1'] 会执行Foo类的 __getitem__方法
obj['k2'] = 'wupeiqi' 会执行Foo类的 __setitem__方法
del obj['k1'] 会执行Foo类的 __delitem__方法
类常用的内置方法
__init__(self,......):初始化对象,在创建新对象前申明
__del__(self):释放对象,在对象被删除之前调用
__new__(self,*args,**ked):实例的生产操作
__str__(self):在使用print语句时调用
__delitem__(self,key):为字典中删除key对应的元素
__setitem__(self,key,value):为字典中的key赋值
__getitem__(self,key):获取序列的索引key对应的值,等价于seq[key]
__len__(self):在调用内联函数len()时被调用
__cmp__(src,dst):比较两个对象src和dst
__getattr__(s,name):获取属性的值
__setattr__(s,name):设置属性的值
__gt__(self,other):判断self对象是否大于other对象
__lt__(self,other):判断self对象是否小于other对象
__ge__(self,other):判断self对象是否不大于other对象
__le__(self,other):判断self对象是否不小于other对象
__eq__(self,other):判断self对象是否等于other对象
__call__(self,*args):把实例对象作为函数调用
__new__():
__new__()在__init__()之前被调用,用于生成实例对象.利用这个方法和类属性的特性可以实现设计模式中的单例模式.单例模式是指创建唯一对象,单例模式设计的类只能实例化一个对象.
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Singleton(object):
__instance = None # 定义实例
def __init__(self):
pass
def __new__(cls, *args, **kwd): # 在__init__之前调用
if Singleton.__instance is None: # 生成唯一实例
Singleton.__instance = object.__new__(cls, *args, **kwd)
return Singleton.__instance
__getattr__()、__setattr__()和__getattribute__():
当读取对象的某个属性时,python会自动调用__getattr__()方法.例如,fruit.color将转换为fruit.__getattr__(color).当使用赋值语句对属性进行设置时,python会自动调用__setattr__()方法.__getattribute__()的功能与__getattr__()类似,用于获取属性的值.但是__getattribute__()能提供更好的控制,代码更健壮.注意,python中并不存在__setattribute__()方法.
代码例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Fruit(object):
def __init__(self, color = "red", price = 0):
self.__color = color
self.__price = price
def __getattribute__(self, name): # 获取属性的方法
return object.__getattribute__(self, name)
def __setattr__(self, name, value):
self.__dict__[name] = value
if __name__ == "__main__":
fruit = Fruit("blue", 10)
print fruit.__dict__.get("_Fruit__color") # 获取color属性
fruit.__dict__["_Fruit__price"] = 5
print fruit.__dict__.get("_Fruit__price") # 获取price属性
__getitem__()、__setitem__()、__delitem_():
如果类把某个属性定义为序列(列表、字典等),可以使用__getitem__()输出序列属性中的某个元素.假设水果店中销售多钟水果,可以通过__getitem__()方法获取水果店中的每种水果,__setitem__()来设置,
代码例子,:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class FruitShop:
def __getitem__(self, i): # 获取水果店的水果
print '__getitem__'
return self.fruits[i]
def __setitem__(self,key,value):
self.fruits[key] = value
print '__setitem__'
if __name__ == "__main__":
shop = FruitShop()
shop.fruits = {}
shop['apple'] = 'red' #["apple", "banana"]
print shop['apple']
输出为:
__setitem__
__getitem__
red
__str__():
__str__()用于表示对象代表的含义,返回一个字符串.实现了__str__()方法后,可以直接使用print语句输出对象,也可以通过函数str()触发__str__()的执行.这样就把对象和字符串关联起来,便于某些程序的实现,可以用这个字符串来表示某个类
代码例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Fruit:
'''Fruit类''' #为Fruit类定义了文档字符串
def __str__(self): # 定义对象的字符串表示
return self.__doc__
if __name__ == "__main__":
fruit = Fruit()
print str(fruit) # 调用内置函数str()出发__str__()方法,输出结果为:Fruit类
print fruit #直接输出对象fruit,返回__str__()方法的值,输出结果为:Fruit类
__call__():
在类中实现__call__()方法,可以在对象创建时直接返回__call__()的内容.使用该方法可以模拟静态方法
代码例子:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Fruit:
class Growth: # 内部类
def __call__(self):
print "grow ..."
grow = Growth() # 调用Growth(),此时将类Growth作为函数返回,即为外部类Fruit定义方法grow(),grow()将执行__call__()内的代码
if __name__ == '__main__':
fruit = Fruit()
fruit.grow() # 输出结果:grow ...
Fruit.grow() # 输出结果:grow ...
b.session实现机制
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
from hashlib import sha1
import os, time
session_container = {}
create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() #创建一个函数,生成session_id
#os.urandom(n) 返回n个随机byte值的string,作为加密使用
class Session(object):
session_id = "__sessionId__"
def __init__(self, request):
session_value = request.get_cookie(Session.session_id) #从客户端传过来的cookie中取session_id值
if not session_value: #如果没有,就生成一个,赋给self._id
self._id = create_session_id()
else:
self._id = session_value #如果有,就取出来赋给self._id
request.set_cookie(Session.session_id, self._id) #设置cookie
def __getitem__(self, key): #取session[key]时返回 session_container[self._id][key]
return session_container[self._id][key]
def __setitem__(self, key, value): #设置session[key],就是设置 session_container[self._id]的key值等于value
if session_container.has_key(self._id): #如果self._id已经在sessiion_container里,就直接设置
session_container[self._id][key] = value
else: #如果不在,就创建字典并赋值
session_container[self._id] = {key: value}
def __delitem__(self, key): #删除session[key]时,删掉session_container[self._id][key]
del session_container[self._id][key]
class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
# my_session['k1']访问 __getitem__ 方法
self.my_session = Session(self) #创建类Session的对象my_session
class MainHandler(BaseHandler):
def get(self):
print self.my_session['c_user'] #返回 session_container[session_id]['c_user']的值
print self.my_session['c_card'] #返回 session_container[session_id]['c_card']的值
self.write('index')
class LoginHandler(BaseHandler):
def get(self):
self.render('login.html', **{'status': ''}) #打开登录页面,返回的status为空
def post(self, *args, **kwargs):
username = self.get_argument('name')
password = self.get_argument('pwd')
if username == 'wupeiqi' and password == '123': #判断提交的用户名和密码,如果正确
self.my_session['c_user'] = 'wupeiqi' #设置session_container[session_id]['c_user']='wupeiqi'
self.my_session['c_card'] = '12312312309823012' #设置session_container[session_id]['c_card']='12312312309823012'
self.redirect('/index') #重定向到 mainhandler
else:
self.render('login.html', **{'status': '用户名或密码错误'}) #如果用户名密码不匹配,返回用户名或密码错误
settings = { #配置信息
'template_path': 'template', #模板路径
'static_path': 'static', #静态文件路径
'static_url_prefix': '/static/', #静态文件路径别名
'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', #设置cookie的加密码
'login_url': '/login'
}
application = tornado.web.Application([ #路由规则
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings)
if __name__ == "__main__":
application.listen(8888) #监听8888端口
tornado.ioloop.IOLoop.instance().start() #启动服务
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。