程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> Python設計形式編程中的備忘錄形式與對象池形式示例

Python設計形式編程中的備忘錄形式與對象池形式示例

編輯:C#入門知識

Python設計形式編程中的備忘錄形式與對象池形式示例。本站提示廣大學習愛好者:(Python設計形式編程中的備忘錄形式與對象池形式示例)文章只能為提供參考,不一定能成為您想要的結果。以下是Python設計形式編程中的備忘錄形式與對象池形式示例正文


Memento備忘錄形式
備忘錄形式一個最好想象的例子:undo! 它對對象的一個狀況停止了'快照', 在你須要的時刻恢回復復興貌。做前端會有一個場景:你設計一個表單,當點擊提交會對表單內容 驗證,這個時刻你就要對用戶填寫的數據復制上去,當用戶填寫的不准確或許格局纰謬等成績, 便可以應用快照數據恢復用戶曾經填好的,而不是讓用戶從新來一遍,不是嘛?

python的例子
這裡完成了一個事務提交的例子

import copy

def Memento(obj, deep=False):

  # 對你要做快照的對象做快照
  state = (copy.copy if deep else copy.deepcopy)(obj.__dict__)
  def Restore():
    obj.__dict__ = state
  return Restore

class Transaction:

  deep = False
  def __init__(self, *targets):
    self.targets = targets
    self.Commit()
  # 模仿事務提交,其實就是初始化給每一個對象往self.targets賦值
  def Commit(self):
    self.states = [Memento(target, self.deep) for target in self.targets]
  # 回滾其實就是挪用Memento函數,履行個中的閉包,將__dict__恢復
  def Rollback(self):
    for state in self.states:
      state()

# 裝潢器的方法給辦法添加這個事務的功效
def transactional(method):
  # 這裡的self其實就是要保留的誰人對象,和類的實例有關
  def wrappedMethod(self, *args, **kwargs):
    state = Memento(self)
    try:
      return method(self, *args, **kwargs)
    except:
      # 和下面的回滾一樣,異常就恢復
      state()
      raise
  return wrappedMethod

class NumObj(object):
  def __init__(self, value):
    self.value = value
  def __repr__(self):
    return '<%s: %r>' % (self.__class__.__name__, self.value)
  def Increment(self):
    self.value += 1

  @transactional
  def DoStuff(self):
    # 賦值成字符串,再自增加確定會報錯的
    self.value = '1111'
    self.Increment()

if __name__ == '__main__':

  n = NumObj(-1)
  print n
  t = Transaction(n)
  try:
    for i in range(3):
      n.Increment()
      print n
    # 這裡事務提交會保留狀況從第一次的-1到2
    t.Commit()
    print '-- commited'
    for i in range(3):
      n.Increment()
      print n
    n.value += 'x' # will fail
    print n
  except:
    # 回滾只會回想到上一次comit勝利的2 而不是-1
    t.Rollback()
    print '-- rolled back'
  print n
  print '-- now doing stuff ...'
  try:
    n.DoStuff()
  except:
    print '-> doing stuff failed!'
    import traceback
    traceback.print_exc(0)
    pass
  # 第二次的異常回滾n照樣2, 全部進程都是修正NumObj的實例對象
  print n

留意
當你要保留的狀況很年夜,能夠會糟蹋年夜量內存


對象池形式
在開辟中,我們老是用到一些和'池'相干的器械,好比 內存池,銜接池,對象池,線程池.. 這裡說的對象池其實也就是必定數目曾經創立好的對象的聚集。為何要用對象池? 創立對象是要支付價值的(我臨時還沒有研討過底層,只說我任務中領會的), 好比pymongo就自帶線程池,如許用完就放回到池裡再被重用,豈不是節儉了創立的消費?

python的例子
我這裡完成了個線程平安的簡略的對象池

import Queue
import types
import threading
from contextlib import contextmanager

class ObjectPool(object):

  def __init__(self, fn_cls, *args, **kwargs):
    super(ObjectPool, self).__init__()
    self.fn_cls = fn_cls
    self._myinit(*args, **kwargs)

  def _myinit(self, *args, **kwargs):
    self.args = args
    self.maxSize = int(kwargs.get("maxSize",1))
    self.queue = Queue.Queue()
  def _get_obj(self):
    # 由於傳出去的能夠是函數,還能夠是類
    if type(self.fn_cls) == types.FunctionType:
      return self.fn_cls(self.args)
    # 斷定是經典或許新類
    elif type(self.fn_cls) == types.ClassType or type(self.fn_cls) == types.TypeType:
      return apply(self.fn_cls, self.args)
    else:
      raise "Wrong type"

  def borrow_obj(self):
    # 這個print 沒用,只是在你履行的時刻告知你今朝的隊列數,讓你發明對象池的感化
    print self.queue._qsize()
    # 如果對象池年夜小還沒有跨越設置的最年夜數,可以持續放出來新對象
    if self.queue.qsize()<self.maxSize and self.queue.empty():
      self.queue.put(self._get_obj())
    # 都邑前往一個對象給相干去用
    return self.queue.get() 
  # 收受接管
  def recover_obj(self,obj):
    self.queue.put(obj)

# 測試用函數和類
def echo_func(num):
  return num

class echo_cls(object):
  pass

# 不消結構含有__enter__, __exit__的類便可以應用with,固然你可以直接把代碼放到函數去用
@contextmanager
def poolobj(pool):
  obj = pool.borrow_obj()
  try:
    yield obj
  except Exception, e:
    yield None
  finally:
    pool.recover_obj(obj)

obj = ObjectPool(echo_func, 23, maxSize=4)
obj2 = ObjectPool(echo_cls, maxSize=4)

class MyThread(threading.Thread):

  def run(self):
    # 為了完成後果,我弄了個簡略的多線程,2個with放在一個處所了,只為測試用
    with poolobj(obj) as t:
      print t
    with poolobj(obj2) as t:
      print t

if __name__ == '__main__':
  threads = []
  for i in range(200):
    t = MyThread()
    t.start()
    threads.append(t)
  for t in threads:
    t.join(True)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved