六角括号在word里怎么打 小括号怎么打( 四 )



1.12.猴子补丁(Monkey patch)

在动态语言中,不去改变源码而对功能进行追加和变更,是在程序运行的过程中去修改 。
1.追加功能 2.功能变更 3.修正程序错误
4.增加钩子,在执行某个方法的同时执行一些其他的处理,如打印日志,实现AOP等 。
class XiaoMing(object):def favorite(self):print "apple"class God(object):@classmethoddef new_xiaoming_favorite(cls):print "banana"@classmethoddef monkey_patch(cls):XiaoMing.favorite = cls.new_xiaoming_favoriteGod.monkey_patch()xiaoming = XiaoMing()xiaoming.favorite()>> banana

1.13.上下文管理器

上下文管理器是一个对象,为操作提供了额外的上下文消息,以一种优雅的方式将额外的处理封装起来 。如果一个类实现了__enter__和__exit__方法则表明该类的实例是一个上下文管理器 。上下文管理器通常和with搭配使用 。实现上下文管理器的两种方式:类和装饰器
类实现上下文管理器

class context(object):def __init__(self):print ('上下文管理器初始化')def __enter__(self):print("上下文管理器开始执行")return selfdef __exit__(self,exec_type, exec_value, exec_traceback):print ("上下文执行结束")def operator(self):print (1/2)with context() as obj:obj.operator()--------------------------------out上下文管理器初始化上下文管理器开始执行0.5上下文执行结束

备注 :当operator改为1/0时,程序执行后抛出异常;但是当在exit方法中返回True时(默认为False),程序不会报错,因为结果返回true就表示告诉python解释器,异常已捕获并解决,不需要往外抛了 。
装饰器实现上下文管理器
可以不用写一个类来实现上下文管理器,类的实现过于繁杂 。python提供了一个装饰器,只需按照它的协议来实现函数内容,即可以将该函数对象变成一个上下文管理器 。

from contextlib import contextmanagerfrom traceback import format_exc@contextmanagerdef context(a,b):print ("上下文管理器开始运行")#enter方法f=a/btry:yield fexcept Exception:print ("处理异常")finally:print("finally")with context(1,2) as f:print (123)print(f)----------------------------------out上下文管理器开始运行1230.5finally

备注:try之前的代码会在装饰器的__enter__方法中执行;当执行到yield时,它的产出值会作为__enter__的返回值,赋值给as后的变量 。当with块的代码执行完成后,上下文管理器会在yield处恢复,继续执行yield后的代码,后面的代码在装饰器的__exit__方法中被调用 。
当程序发生异常时,后面的代码不会执行(包括finally代码)
上下文管理器类与@contextmanager中最大的区别在于对异常的处理 。以类的方式实现的上下文管理器,在引发异常时,exit方法内的代码仍会正常执行;而以生成器函数实现的上下文管理器,在引发异常时,exit方法会将异常传递给生成器,如果生成器无法正确处理异常,则yield之后的代码不会执行 。
1.14. 可散列的数据类型

如果一个对象是可散列的,那么在这个对象的生命周期中,它的散列值是不变的,而且这个对象需要实现 __hash__() 方法 。另外可散列对象还要有 __eq__() 方法,这样才能跟其他键做比较 。如果两个可散列对象是相等的,那么它们的散列值一定是一样的 。原子不可变数据类型(str、bytes 和数值类型)都是可散列类型 。
1.15. Python 运行时

python -m xxx#相当于import,当作模块运行,当前脚本路径不会加入到sys.path中 。python xxx.py#直接运行,当前脚本路径会加入到sys.path中 。python -m site #显示sys.path的值内容,即python搜索模块的目录

1.16. 原地操作

许多运算符都有原地操作,如add方法对应的原地操作是iadd 。python中的运算符和operator模块中的函数是对应的
不可变类型的目标

对于不可变的目标如字符串、数字、元组等,当调用一个原地方法是,分两步执行,运算和赋值 。当调用原地函数时,只执行运算嘛,不执行赋值操作 。如下:
>>> import operator>>> a="hello">>> operator.iadd(a, ' world')#若要更新变量,则需要执行赋值操作,即a=operator.iadd(a, ' world')'hello world'>>> a'hello'

可变类型的目标
对于可变的目标,如列表、字典,原地方法将执行更新,因此不需要后续赋值操作 。如下:

>>> import operator>>> s = <'h', 'e', 'l', 'l', 'o'>>>> iadd(s, <' ', 'w', 'o', 'r', 'l', 'd'>)<'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'>>>> s