Python语言基础考察二(key words:monkey patch & 自省 & 列表字典推导 & Python之禅)

本文重点讨论monkey patch & 自省 & 列表字典推导 & Python之禅

一、monkey patch

先讲故事:

这个词原来是Guerrilla Patch(杂牌军、游击队),意思是这部分不是原装的,后来因为guerilla发音和gorllia(猩猩)相似,就演变成了了 gorllia patch,再到后来变成了现在的monkey patch。

猴子补丁(Monkey Patch):属性在运行时动态替换

  • Monkey patch就是在运行时对已有的代码进行替换,达到hot patch的目的。
  • 比如 gevent 库需修改内置 socket
  • from gevent import monkey
    monkey.patch_socket()
    设置后就将原本的 socket 模块替换成非阻塞的 socket 模块
import socket
print(socket.socket)

print("after monkey patch")
from gevent import monkey
monkey.patch_socket()
print(socket.socket)

运行结果:

<class 'socket.socket'>
after monkey patch
<class 'gevent._socket3.socket'>

如果自己实现这样的功能可以这样做,例如 time.time() 函数:

import time
print(time.time())

def _time():
    return 1234

time.time = _time

print(time.time())

结果:

1561413751.8529987
1234

二、自省

Introspection:

  • 自省指的是在运行的时候判断一个对象的类型的能力
  • Python 一切皆对象,用 type、isinstance、id 获取对象类型的信息
  • Inspect 模块提供了更多获取对象信息的函数
>>> a = [1,2,3]
>>> b = 'philip'
>>> type(b)
<class 'str'>
>>> isinstance(b,list)
False
>>> isinstance(a,list)

注意在使用 id 的时候需要注意 is 与 == 的区别

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> a is b
False
>>> id(a)
1610798064584
>>> id(b)
1610797790280
>>> a == b
True
>>> a[1] is b[1]
True

这段演示代码的核心在最后一行,为什么这个地方用 is 判断的时候结果是 True 呢?缘由在于Python的小数预存机制,感兴趣的读者可以自行查询此机制,还可以自行尝试 a = 1,b = 1,去判断 a is b,你会发现返回 True

三、列表和字典推导

1、列表推导(list comprehension):

>>> list1 = [[x,y] for x in range(4) for y in range(3) if y%2 == 0]
>>> list1
[[0, 0], [0, 2], [1, 0], [1, 2], [2, 0], [2, 2], [3, 0], [3, 2]]

注意:如果是(i for i in range(10) if i%2 == 0),则返回的是一个生成器,使用list可以对其转换类型

>>> list2 = (i for i in range(10) if i%2 == 0)
>>> list2
<generator object <genexpr> at 0x000001770B08D360>
>>> list3 = list(list2)
>>> list3
[0, 2, 4, 6, 8]

2、字典推导式(dictionary comprehension):
字典推导式的基本格式是:{ key_expr: value_expr for value in collection if condition }

>>> a = [1,2,3,4,5,6]
>>> b = ['a','b','c','d','e']
>>> dict1 = {key : val for key,val in zip(a,b)}
>>> dict1
{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

注意:当 key 多于 val 时,代表多的键就没有对应的值,就不会显示了;同理,如果多余的 val 没有 key 与其对应时,也不会显示了。

四、python之禅

The Zen Of Python:

  • Tim Peter 编写的关于python编程的准则
  • import this 就可以打印出来
  • 当编程风格拿捏不准的时候可以参考

代码演示

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

翻译(括号之中的内容是我自己认为写代码的时候可以注意的地方):

  • 优美胜于丑陋(写出优雅的代码,有良好的代码风格)
  • 明了胜于晦涩(规范命名规则,避免一行代码想做到过大的作用而超长)
  • 简单胜于复杂(简单明了的表达胜于复杂)
  • 复杂胜于更加复杂(如果实在避免不了复杂,那么也要尽量简单,例如保持接口的简单)
  • 扁平胜于嵌套(不要有太多的嵌套,笔者曾经见过嵌套五个for循环的,能把人看死=_=)
  • 间隔胜于紧凑(代码之间应该有间隔区分,方便阅读)
  • 可读性很重要(Python的一大特点,可读性强)
  • 特殊也不能打破规则(规则不可以被打破,例如命名的规则)
  • 就算再怎么实用,也不能容忍错误,除非你确认要那样做了
  • 面对有争议的代码时,拒绝瞎猜,而是找一种(最好只有一种)显而易见的方法去做,尽管这种方法可能一开始并不那么显而易见
  • 现在动手比永远不动手好得多,但是那些“不正确的”动手还不如不动手(不经思考的动手还不如不动手)
  • 如果方案很难描述,那么这就是一个坏的方案
  • 如果方案容易描述,或许这就是一个好的方案
  • 命名空间是一种绝妙的思想,我们应该多尝试着使用(namespace在Django里面用到了,有的时候我会避免出错而逃避使用namespace,但是看了这个文档之后我决定研究一下……)

额……你以为这块儿我说完了?其实并没有……,有一个很恶搞的东西,当去查看this的源码的时候,会发现它是这样的:
s = “”“Gur Mra bs Clguba, ol Gvz Crgref
Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera’g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh’er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna evtug abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg’f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn – yrg’f qb zber bs gubfr!”""
d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)
print("".join([d.get(c, c) for c in s]))
额……我佛了,作者还搞了一个这样的加密在这里,城会玩(ヾ§  ̄▽)ゞ2333333


下期预告:

  1. python 2/3 差异汇总
  2. Python 2/3 的转换工具

嘿嘿,I am very glateful that 你看到这里了哦~下回再见ヾ(o◕∀◕)ノヾ
Thx
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值