范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

面试官你相信吗,我只用两个函数实现事务!(设计模式)

  主题  设计模式    Python
  大家好,今天给大家介绍一个新的设计模式,叫做memento模式。
  memento在英文当中是纪念品的意思,在这里,指的是对象的深度拷贝。通过对对象深度拷贝的方法来 实现事务的功能 。有了解过数据库的小伙伴们应该都知道,在数据库当中有些操作是绑定的, 要么一起执行成功,要么一起不执行,绝对不运行某些操作执行了,某些操作没有执行的情况发生 。这一点就被称为事务。
  深度拷贝
  我们先来简单回顾一下Python当中的拷贝。
  拷贝在很多语言当中都有对应的函数,在Python当中也不例外。Python中的拷贝函数有两个,一个是copy,另外一个是deepcopy。也就是常说的深拷贝和浅拷贝,这两者的区别也非常简单,简而言之就是 浅拷贝只会拷贝父类对象,不会拷贝父类对象当中的子对象 。
  我们来看一个例子,在下图当中b是a的浅拷贝,我们可以看到当a[2]当中插入了5之后,b当中同样也多了一个5。因为它们下标2存储的是同一个引用,所以当a当中插入的时候,b当中也发生了同样的改变。我们也可以看到,当我们改变了a[0]的时候,b当中则没有发生对应的改变。因为a[0]是一个数字,数字是基础类型直接存储的值而不是引用。
  与浅拷贝对应的就是深拷贝,我们可以看到,当a[2]当中插入元素的时候,深度拷贝出来的b并不会发生对应的变化。
  memento
  利用拷贝,我们可以实现memento函数,它的作用是 给对象做备份 。在Python当中,对于一个对象obj来说,它所有的成员以及函数等信息全是储存在 obj.__dict__  这个dict当中的。也就是说如果我们将一个对象的 __dict__  拷贝一份的话,其实就相当于我们把对象拷贝了一份。
  通过使用拷贝,我们可以很容易实现memento函数,我们先来看代码吧。from copy import copy, deepcopy  def memento(obj, deep=False):     state = deepcopy(obj.__dict__) if deep else copy(obj.__dict__)      def restore():         obj.__dict__.clear()         obj.__dict__.update(state)          return restore
  memento是一个高阶函数, 它返回的结果是执行函数,而不是具体的执行结果 。如果对高阶函数不太熟悉的同学,可以去回顾一下Python当中高阶函数的相关内容。
  这里面的逻辑不难理解,传入的参数是一个obj的对象和一个bool型的flag。flag表示使用深拷贝或浅拷贝,obj就是我们需要做对应快照或者是存档的对象。我们希望在对象框架不变的基础上恢复其中的内容,所以我们拷贝的范围很明确,就是 obj.__dict__  ,这当中存储了对象的所有关键信息。
  我们看下restore这个函数,当中的内容其实很简单,只有两行。第一行是清空obj目前 __dict__  当中的内容,第二步是用之前保存的state来还原。其实restore执行的是一个 回滚obj的功能,我们捋一下整个过程。我们运行memento函数会得到restore这个函数,当我们执行这个函数的时候,obj当中的内容会回滚到上次执行memento时的状态。
  理解了memento当中的逻辑之后,距离我们实现事务就不远了。关于事务我们有两种实现方法,一种是通过对象,一种是通过装饰器,我们一个一个来说吧。
  Transaction对象
  面向对象实现的方式比较简单,它和我们平时使用事务的过程也比较近似。Transaction对象当中应该提供两个函数,一个是commit一个是rollback。也就是说 当我们执行成功之后我们执行commit,对执行的结果进行快照。如果执行失败则rollback,将对象的结果回滚到上一次commit时的状态 。
  我们理解了memento函数之后,会发现commit和rollback刚好对应执行memento函数以及执行restore函数。这样我们不难写出代码:class Transaction:      deep = False     states = []      def __init__(self, deep, *targets):         self.deep = deep         self.targets = targets         self.commit()      def commit(self):         self.states = [memento(target, self.deep) for target in self.targets]      def rollback(self):         for a_state in self.states:             a_state()
  由于我们需要事务的对象可能不止一个,所以这里的targets设计成了数组的形式。Transaction装饰器
  我们也可以把事务实现成装饰器,这样我们可以通过注解的方式来使用。
  这里的代码原理也是一样的,只不过实现逻辑基于装饰器而已。如果对装饰器熟悉的同学,其实也不难理解。这里的args[0]其实就是某一个类的实例,也就是我们需要保证事务的主体。from functools import wraps  def transactional(func):     @wraps(func)     def wrapper(*args, **kwargs):         # args[0] is obj         state = memento(args[0])         try:             func(*args, **kwargs)         except Exception as e:             state()             raise e     return wrapper
  这是常规装饰器的写法,当然我们也可以用类来实现装饰器,其实原理差不多,只是有一些细节不太一样。class Transactional:      def __init__(self, method):         self.method = method      def __get__(self, obj, cls):         def transaction(*args, **kwargs):             state = memento(obj)             try:                 return self.method(*args, **kwargs)             except Exception as e:                 state()                 raise e         return transaction
  当我们将这个注解加在某一个类方法上,当我们执行obj.xxx的时候,就会执行Transactional这个类当中的 __get__  方法,而不是获得Transactional这个类。并且把obj以及obj对应的类型作为参数传入,也就是这里的obj和cls的含义。这个是用类来实现装饰器的常规做法,我们贴一下常规的代码,来比较学习一下。class Wrapper:     def __init__(self, func):         wraps(func)(self)      def __call__(self, *args, **kwargs):         return self.__wrapped__(*args, **kwargs)      def __get__(self, instance, cls):         if instance is None:             return self         else:             return types.MethodType(self, instance)
  这是一个用类来实现装饰器的case,我们可以看到在 __get__  这个函数当中返回的是self,也就是返回了Wrapper这个类。类通常是不能直接执行的,为了让它能够执行,这里给它实现了一个 __call__  函数。如果还是看不明白也没有关系,可以忽略这部分。用类实现装饰器也不常见,我们熟悉高阶函数的方法就可以了。实战
  最后我们来看一个实际应用的例子,我们实现了一个NumObj的类,兼容了上面两种事务的使用,可以对比一下看看区别。class NumObj:     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 do_stuff(self):         self.value += "111"         self.increment()                   if __name__ == "__main__":     num_obj = NumObj(-1)      a_transaction = Transaction(True, num_obj)  # 使用Transaction     try:         for i in range(3):             num_obj.increment()             print(num_obj)          a_transaction.commit()         print("----committed")         for i in range(3):             num_obj.increment()             print(num_obj)         num_obj.value += "x"         print(num_obj)     except Exception:         a_transaction.rollback()         print("----rollback")      print(num_obj)  # 使用Transactional     print("-- now doing stuff")     num_obj.increment()      try:         num_obj.do_stuff()     except Exception:         print("-> doing stuff failed")         import sys         import traceback         traceback.print_exc(file=sys.stdout)      print(num_obj)
  从代码当中,我们不难发现对于Transaction也就是面向对象实现的,我们 需要额外创建一个Transaction的实例来在try catch当中控制是否执行回滚 。而使用注解的方式更加灵活,它 执行失败会自动执行回滚 ,不需要太多的额外操作。
  一般来说我们更加喜欢使用注解的方式,因为这样的方式更加简洁干净,更加pythonic,能够体现出Python的强大。而第一种方法显得有些中规中矩,不过好处是可读性强一些,代码实现难度也低一些。大家如果在实际工作当中有需要用到,可以根据自己的实际情况去进行选择,两种都是不错的方法。
  今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持 吧~( 点赞、关注、转发 )
  原文  http://www.cnblogs.com/techflow/p/14297395.html

余承东太狠,华为拿下全球第一!网友生气能不能不要这么低调?说起余承东,很多人知道,他除了是华为现任消费者BGCEO华为终端公司董事长之外,还有更多的人知道,他有一个外号叫做余大嘴。之所以会这么叫他,就是因为在前几年,余承东在新闻采访上是满摩托罗拉真香机开卖!米粉疯狂抢购2分钟,雷军连忙喊话高通2月3日,万众期待的摩托罗拉edges正式开卖!为什么说是万众期待呢?其实这就跟当年的小米手机一样,性价比非常高,被网友称为真香机!摩托罗拉edges全球首发骁龙870旗舰处理器,国产之光?自研5G芯片,手机续航可顶3天,一年却只卖出84台手机是否支持5G网络取决于处理器是否是5G芯片,目前能够制造处理器并且愿意出售的基本只有高通与联发科。因此,手机的价格也一般是被这两家公司所卡住。例如高通推出骁龙765G市场中才逐3款黑科技扫地机器人大盘点,从参数到清单,直接揭露哪款值?经济水平的提升使得大家消费水平日益增强,为了贴近大家的购物需求减轻室内家务清洁负担,扫地机器人成为了时下最炙手可热的产品。扫地机器人打破了传统清洁辅助工具被动清扫的特性,实现了智能被全球封杀的软件,运行起来比360还流氓!13亿网民深受其害电脑中最大的流氓软件是谁,很多人会说360,有网友还表示安装了360之后,电脑就变卡了。有一说一,360在电脑上确实不怎么样,但手机版的360极速浏览器还是可以的。360在国内口碑巨头闷声发大财!国内用户误以为它要倒闭,它却握住国产手机命脉正所谓没有人会一直走运,也没有任何品牌能够一直风光。当年小米凭借性价比位列全国第一,如今苦苦奋斗却一直与第一无缘。又比如三星,曾经在国内风头也是一时无两,三星s6e更加是让国人都看华为再次自研猪肉!领先三星2年,网友雷军真的是预言家啊实体清单可以说是将华为逼得退无可退,在手机市场上,华为剩下的是会用完的芯片,怎么分配是最大的难题。两轮制裁下来,华为自研的芯片都被无法生产出来,甚至华为消费者业务CEO余承东都表示无数90后的回忆手机!续航比诺基亚还强,还能同时登录8个微信现在国内的智能手机市场可以说只剩下几个巨头,想起几年前,那可是群芳争艳,各种品牌的手机如雨后春笋。但竞争者越多,就越需要厂商靠更多的产品来打动用户,于是当时就衍生出了很多手机品牌,发布隔空充电之后,小米11又展示黑科技!网友永久续航不是梦今天上午10点多,小米正式发布了隔空充电技术,虽然功率只有5w,但是这不失为一个正确的方向。然而却有网友发现,在今天上午8点多,摩托罗拉就就已经发布了隔空充电技术,在距离一米的位置国产手机是扶不起的阿斗?华为一旦退下来,得益最大的竟然是苹果从iPhone4开始,苹果手机开始收割全球市场!每次新机发布必然会上热搜,线下店也会人满为患。然而,近年来iPhone却遇到了一个劲敌国产手机华为。华为擅长通信领域,但能够跨界成长对待华为鸿蒙OS系统的两种态度国内在疯狂嘲讽,谷歌却慌了记得在上个世纪90年代的时候,一位美国科学家说我们可以随时关闭中国发电厂的发电机,让他们再也打不开!为什么美国人能够随时关闭我们的发电机?原因就是我们发电机的核心技术都是来自美国,
让团聚更安心寒风凛冽,雨雪纷纷,我们短暂告别忙碌的生活,如倦鸟归巢一般,奔向温暖的家拥抱挚爱的人。我们眷恋家的一方温暖,更希望能守护家人健康平安。华为智选720全效空气净化器愿为全家人的健康呼奥密克戎有多严重?专家它的50个突变可能导致其灭亡侨报网报道南非医学研究理事会(SouthAfricanMedicalResearchCouncil)最新研究报告显示,奥密克戎(Omicron)变种病毒可能不会导致严重的疾病症状。滴滴三面全过程一面1小时左右1。自我介绍2。详细解释微服务如何实现服务发现与注册以如果某个服务挂掉,如何通知调用者3。聊简历中的项目,项目细节,挑战,遇到哪些实际问题,是如何解决的4。mongo新年礼物推荐诺基亚T20教育版学习平板元旦春节新年假期即将来临,这个时候,大家一定都在忙着为亲朋好友挑选礼物。如果您正烦恼应该选择什么礼物最能体现自己的心意,而恰好亲戚朋友或者您自己家里有孩子的话,那么我想与你分享这款你的手机为什么越来越卡?有没有一部手机坚持用了五年的?有。其实我现在还在用华为畅享9,单位发的。虽然没有5年,但之前发的也照样能用,硬件的确落后,但并不卡。大概也是因为我不玩手机游戏吧。我拿到手机以后,都要进行调整。首先是一般人都知道华为预计收入约6340亿元,同比降28。9,说明什么?华为在官网上发布了2022年新年致辞,其中预计2021年全年实现销售收入约6340亿人民币。但是对比2020年的收入总额8914亿元,发现下降了28。9,其中预计在第四季度营收同比2021年进入尾声,多款手机开始清仓,带你正确捡漏好手机2021年进入尾声,多款手机开始清仓,以下三款手机大家可以购买中端机摩托罗拉edges摩托罗拉edges在性能方面搭载旗舰级5G芯片骁龙8707nm工艺制作工艺,支持WiFi6及蓝两台电脑用什么软件能实现远程控制?我分别从系统自带和第三方软件介绍6中远程控制软件,希望可以帮助到你。系统自带1windows自带远程桌面连接远程桌面连接,是Win10专业版系统自带的远程连接功能,使用远程桌面连接听说小米11u摄像方面超好,真的有说的那么好吗?我有11U,其实并没说的那么好,说什么夜宵算法,其实极暗的环境还是拍不清楚的,我亲测过,然后,只有主摄像头带夜景模式,长焦跟广角不带,先说广角,假设你去KTV玩,光线不好,你想给大小米模特也是眯眯眼!荣耀的妆容类似于眯眯眼?小米模特也是眯眯眼!荣耀的妆容类似于眯眯眼?这说明什么?说明中国4A广告界的审美艺术,审美观念完全掌握在西方人的手里,4A原来就是美国人提出来的。当美国将中国视为对手时,美国的变态IT界的热宠,向日葵C1Pro插座亮相,几十块就能搞定远程开关电脑前文打工人被抓壮丁这不常有的事么,重要的大活也就无所谓了,就怕是一些鸡毛蒜皮的小活,发个文件找个合同,也得跑回公司一趟,其实,如果能远程控制电脑的话,就不用跑一趟了,但是,一般下了