• 猴子补丁


    II.猴子补丁

    • 猴子补丁是python特有设计模式,是一个非常强悍,非常有趣设计模式。能够使用很少修改达到全局运行,修改。

    • 需要你深入理解模块的天然单例原理,要深入理解from a import fun ->fun() 和 import a->a.fun()区别,否则猴子补丁失效或部分地方失效。要深刻理解猴子补丁为什么最好要在运行的模块最顶行打的本质原理。

      利用a.py   b.py run.py 然后需要把import 改成  from import 测试对比,以及把run里面的 import b放在打猴子补丁之前和打猴子补丁之后对比结果。
      
    • 利用模块只会导入一次,模块天然单例的特性,使用猴子补丁。一处修改 处处生效。对多人合作的大项目,如果猴子补丁直接在__init__.py里面执行了,并且猴子补丁变化有很大影响,则需要告诉小伙伴,免得出现莫名其妙的疑惑。

    • a.py

      def fun():
          print("原始 print hello <a>")
      
    • b.py

      from monkey_tes.a import fun
      def funb():
          print("fun b 中调用func")
          fun()
      
    • run.py

      from monkey_tes import a
      
      from monkey_tes.b import funb
      
      def modify_fun():
          print("修改后 print hello <run>")
      
      
      a.fun = modify_fun
      a.fun()
      
      print("-"*40)
      # from monkey_tes.b import funb
      
      funb()
      """
      如果在第19行,即打了猴子补丁后再导入funb,结果是:
      
          修改后 print hello <run>
          ----------------------------------------
          fun b 中调用func
          修改后 print hello <run>
      
      如果在开头行,即在打猴子补丁之前导入funbbb,结果是:
      
          修改后 print hello <run>
          ----------------------------------------
          fun b 中调用func
          原始 print hello <a>
      """
      # 开头导入funb,因b.py文件引入还是a.fun 所以在执行funb()时候,还是会执行a的fun.
      # 但在打完猴子补丁后导入funb,此时a的fun为modify_fun.所以执行funb内的a.fun,其实执行的是modify_fun
      
    • 示例:

      import json
      from datetime import datetime as _datetime
      from datetime import date as _date
      
      class _CustomEncoder(json.JSONEncoder):
          """自定义的json解析器,mongodb返回的字典中的时间格式是datatime,json直接解析出错"""
      
          def default(self, obj):
              if isinstance(obj, _datetime):
                  return obj.strftime('%Y-%m-%d %H:%M:%S')
              elif isinstance(obj, _date):
                  return obj.strftime('%Y-%m-%d')
              else:
                  return json.JSONEncoder.default(self, obj)
      
      
      # noinspection PyProtectedMember,PyPep8,PyRedundantParentheses
      def _dumps(obj, skipkeys=False, ensure_ascii=False, check_circular=True, allow_nan=True, cls=_CustomEncoder, indent=None, separators=None,
                 default=None, sort_keys=False, **kw):
          if (not skipkeys and ensure_ascii and check_circular and allow_nan and cls is None and indent is None and separators is None and default is None and not sort_keys and not kw):
              return json._default_encoder.encode(obj)
          return cls(
              skipkeys=skipkeys, ensure_ascii=ensure_ascii,
              check_circular=check_circular, allow_nan=allow_nan, indent=indent,
              separators=separators, default=default, sort_keys=sort_keys, ).encode(obj)
      
      
      def monkey_patch_json():
          json.dumps = _dumps
      
      
      if __name__ == '__main__':
          dictx = {'a':1,'b':_datetime.now()}
          monkey_patch_json()   # 不打猴子补丁时候,datetime是python自定义对象,不能被json序列化,程序会出错。
          print(json.dumps(dictx))
      
  • 相关阅读:
    【python之路39】Python 正则表达式
    【html、CSS、javascript-4】新特征之增强表单
    node调试工具--node-inspector安装
    node多版本管理--nvmw
    transform的影响
    HTML5 input事件检测输入框变化[转载]
    mysql5.7.16安装 初始密码获取及密码重置
    undefined 与void 0
    html 自定义标签使用实现方法
    图片轮播滚动
  • 原文地址:https://www.cnblogs.com/xujunkai/p/13463784.html
Copyright © 2020-2023  润新知