谁能告诉我这个笑话的意思啊 JavaScript 程序员和 Python 程序员相遇了。 P

Python016

谁能告诉我这个笑话的意思啊 JavaScript 程序员和 Python 程序员相遇了。 P,第1张

JS: 说的是数字和字符串相加,都会先转换成字符串

'1' + 1 =>11

1 + '1' =>11

Python: 说的是duck typing ,方法一样就行,不管你的具体类型

“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

你好,很高兴为你解答。猴子补丁的由来首先说个我自己的笑话,话说Python算是我接触的稍微深点儿的第一门动态语言,用Python没多久就知道了有个Gevent,学习Gevent没多久就知道有个“猴子补丁”的概念。最开始觉得这么名字挺乐呵,猴子补丁,为啥叫这么个名儿?是因为猴子的动作迅速灵敏,Gevent也有这个特点,所以叫猴子补丁么?然后这几天在看《松本行弘的程序世界》这本书,里面专门有一章讲了猴子补丁的设计,我就笑了,原来猴子补丁不是我理解的这个意思,更不是Gevent最开始这么做的。所谓的猴子补丁的含义是指在动态语言中,不去改变源码而对功能进行追加和变更。猴子补丁的这个叫法起源于Zope框架,大家在修正Zope的Bug的时候经常在程序后面追加更新部分,这些被称作是“杂牌军补丁(guerillapatch)”,后来guerilla就渐渐的写成了gorllia(猩猩),再后来就写了monkey(猴子),所以猴子补丁的叫法是这么莫名其妙的得来的。从Gevent学习猴子补丁的设计猴子补丁这种东西充分利用了动态语言的灵活性,可以对现有的语言Api进行追加,替换,修改Bug,甚至性能优化等等。比如gevent的猴子补丁就可以对ssl、socket、os、time、select、thread、subprocess、sys等模块的功能进行了增强和替换。我们来看下gevent中的猴子补丁模块gevent.monkey的设计和实现,以后如果自己要设计实现猴子补丁,也可以按照这么个模式去做,我最近比较喜欢用ipython来阅读python模块的代码,执行importgevent.monkey之后,只需要输入??gevent.monkey就可以查看源码了。这个模块核心的函数其实就这几个,这些函数都位于模块的上方,get_original、patch_item、remove_item、patch_module还有一个全局变量叫做saved,默认指向一个空的字典对象。首先来看patch_item函数的实现:defpatch_item(module,attr,newitem):NONE=object()olditem=getattr(module,attr,NONE)ifolditemisnotNONE:saved.setdefault(module.__name__,{}).setdefault(attr,olditem)setattr(module,attr,newitem)这个函数的功能就是从指定模块中查找旧的项,并把旧的项保存到saved字典中,然后将旧项替换成新项。这里没有使用None,而是构建了一个空的object()作为默认属性,是NullPointer模式么?然后是patch_module的实现:defpatch_module(name,items=None):gevent_module=getattr(__import__('gevent.'+name),name)module_name=getattr(gevent_module,'__target__',name)module=__import__(module_name)ifitemsisNone:items=getattr(gevent_module,'__implements__',None)ifitemsisNone:raiseAttributeError('%rdoesnothave__implements__'%gevent_module)forattrinitems:patch_item(module,attr,getattr(gevent_module,attr))gevent有个约定,作为补丁的gevent模块要包含这两个属性,__target__和__implements__,__target__是被补丁的默认模块名称,可以不指定,默认为gevent子模块的名称,比如gevent.socket是socket模块的补丁,__implements__是要进行补丁的属性,这是gevent.socket模块中__implements__的定义:#standardfunctionsandclassesthatthismodulere-implementsinagevent-awareway:__implements__=['create_connection','socket','SocketType','fromfd','socketpair']patch_module的工作就是从gevent模块里面读取这两个属性,然后遍历调用patch_item进行替换。可是有的时候我们不希望用补丁的东西,而是使用原先的模块去进行处理,该怎么?前面提到过进行patch_item的时候会把旧的属性保存到名为saved的全局字典里面,如果要获得旧的模块属性,那么就要调用get_original函数从saved字典里面取出来。In[6]:sleep=gevent.monkey.get_original("time","sleep")In[7]:sleepOut[7]:In[8]:importtimeIn[9]:time.sleepOut[9]:猴子补丁猴子补丁的功能很强大,但是也带来了很多的风险,尤其是像gevent这种直接进行API替换的补丁,整个Python进程所使用的模块都会被替换,可能自己的代码能hold住,但是其它第三方库,有时候问题并不好排查,即使排查出来也是很棘手,所以,就像松本建议的那样,如果要使用猴子补丁,那么只是做功能追加,尽量避免大规模的API覆盖。希望能帮到你,求采纳。