首页 > 编程知识 正文

python黑魔法手册(python魔法方法详解)

时间:2023-12-24 12:05:45 阅读:320878 作者:SHCS

本文目录一览:

Python有哪些黑魔法?

当然,Python的黑魔法是所有的内省和动态绑定。

例如,Python可以重新绑定解释器的异常,以便在程序异常结束时可以进行一些自定义处理。

一旦你重置了异常钩子,一旦你的代码抛出一个异常,整个解释器的环境将被ipdb接管,然后被用作交互模式。通常,我将检查堆栈并pickle必要的对象,因此稍后再犯错误更容易。

由于IPython是一个非gui程序,所以即使在SSH中也可以使用它,这是SSH缺少IDE的完美解决方案。

动态绑定的另一个用途是,当程序依赖于修改后的库时,可以将修改后的部分剥离,并在运行时动态绑定到相应的库。

在内省中,Python可以通过dir()和help()函数获取列表并帮助对象的成员,当您找不到库文档时,这些函数非常有用。只要开发人员在函数下面写注释,您就可以在帮助中看到它。

除了上面提到的特性之外,python还有一些小技巧,还有一些其他的答案。尽管它们中的许多都是语法上的糖,但它们可以使程序更有python:使用槽使成员静态,您可以节省大量的内存。装饰器,常用的功能,例如函数计时,也可以用来生成新的函数签名。函数签名可以影响传递检查和ide完成,这对于具有不确定的长参数的函数非常有用。许多库使用这种方法来处理不同版本的API。生成器,它可以为仅仅遍历数据保存大量的内存。参数也展开了。

典型的例子是zip(listx)和链(listx),它们分别对应于转置和连接。如果name==“main”:检查主程序是否被调用,主程序必须与多处理并行使用这个框。例如,枚举将列表转换为list2index可以用于((x,I)for I,枚举列表中的x(listx))namedtuple,生成类似于C语言的结构,并支持所有元组的语法。不初始化该词的defaultdictionary可以使用lambda来实现嵌套结构默认的结构的嵌套结构(lambda:defaultdictionary(int)),或者甚至是递归字典树=lambda:defaultdictionary(树)

有多少人按@萧井陌大神给出的Python+Flask路线找到工作了

今天拿到offer了,一直围观此问题,终于可以轮到我装逼了233

找工作前后花了整好一个月,我是一个月前的今天飞北平。不过第一张简历是上周日投的,投的知乎,然后被拒了,气得我当场卸载了知乎app。然后每天投一份,直到昨天接到面试通知,今天面了一下午通过。

先说一下背景吧。说真的楼上你们这些科班出身甚至本来就从事web前后端的号称花了一个月成功找到相关工作的,真是太打击我们这些转大行的了。

本人211土木专业本科,去年毕业还去工地吃了一年的屎,今年十一月裸辞。Python是大四学的,不过主要是为NumPy去的。

没有任何项目经历,截止到今天为止唯一的项目还是自己的博客,还是两周前动工的,还没写完,前端真的太恶心了,再让我写css自杀。

没做过ACM,没用过Linux,没写过Vim。

没学过网络原理、操作系统、数据结构、数据库。

Matlab技能点倒是丰富;我本科真的毁在数学建模上了。人在做,天在看,数学建模留祸患!

基本就是这样。

到北平后的四周里有两周都花在LeetCode上。不得不说LeetCode大法好啊,今天面试的算法题全是原题,我心里跟撕了一万条藏獒一样爽。

剩下的时间基本都是在Flask里来回折腾,不过真的啃不动啊,我真的不懂什么是TCP协议,什么的socket。今天面试的web基础问题全部跪了,唯一一道答上来的是“说说四种请求方式”,而我只知道get, post, put,太JB感人了。

面试全靠算法和Python基础拿分,稍微问了问MySQL,问的很简单,LeetCode的DB题比这些高到不知道哪里去了;Python问的最高语法居然是生成器,我听说有人都被问到修饰符了吓得我赶紧买了本Python Pocket Reference通宵背了一遍;问了一个Maximum Subarray这个题,我做的时候是用的分治法做的,他们居然不满意,非要引导我想出线性时间算法,但是我根本理解不了面试官在说啥,硬着头皮想出一个双指针算法居然得到了好评;二面的时候问的如何列表去重,空间复杂度和时间复杂度一步步做要求时的不同算法,然后让我实现了一遍MergeSort;问了问Vim的几个常用命令,小case。

然后HR来谈待遇,就过了。。。

说一下公司,A轮融资完成,130人规模,O2O,待遇没超过10k,爬虫岗,虽然我从来没有写过爬虫。

列一下书单吧:

Python类

Python CookBook,我一直把这书翻译为Python黑魔法,尤其到元编程那章,真他妈黑。

Learning Python,大四时候就是抱着这书入门的,不过坑爹的中译本居然把装饰器、修饰符、元类这么重要的部分给贸然截除了,我已经报警很多次了。

编写高质量代码——改善Python程序的91个建议,我完全用来当做查漏补缺的作用了,比如看看自己对mro的理解有没有偏差什么的。

Python Pocket Reference,纯粹是为了应付面试,我怕他问我内置函数或者常用的标准库。

没有了

Web类

Flask Web开发,就是萧大推荐的啦,虽然一遍一遍地看也还是停留在默写出代码的水平,但是我会努力把Flask源码也背下来的!(大误)

Head First HTML and CSS,我真的好想说,这本书的信息量密度好低啊,书又那么贵又厚,害得我花了一天时间才看完,而且看完后基本忘完了。

深入理解Bootstrap,纯粹是为了写我的博客买的,买了以后才发现,妈的,不是有中文官网吗。

图解TCP/IP,花了一天看完,看完后觉得自我感觉良好,结果还是看不懂Python Cookbook第11章,很难过。

没有了

其他

Learning SQL,好书啊,真的推荐,虽然概念解释得稀烂,比如我是直到今天早上才知道应该怎么回答“谈谈事务吧”,还是上网搜的。

GitHub入门,千万别买,因为你就算看完后还是不知道该如何push你的代码到你的repository,直接上GitHub看tutorial好了。

挑战程序设计竞赛,非常低调的书名,但是真的太棒了!我的数据结构和算法全是从上面学到的!应付面试的话图论之后的不用看了,但是我不得不说网络流那章非常精彩!

Vim实用技巧,非常棒,让你逼格提升一个数量级。

没有了

我不去继续写我的博客又在知乎装逼了,今天的contribution又废了。。

祝愿所有的转行生都一切顺利!

说完了,求赞。

求《Python黑魔法指南2.0》全文免费下载百度网盘资源,谢谢~

《Python黑魔法指南2.0》百度网盘pdf最新全集下载:

链接:

?pwd=8mkk 提取码:8mkk

简介:作者(明哥)是一个从事云计算多年的 Python 重度用户,他把自已多年的 Python 编码经验整理成小册子。

全书合计将近 5 万字,收录了近 100 条的 Python Tips,没有长篇大论,每一篇都是精品,可以让你一天之内,就能收获别人几年的 Python 技能及魔法知识。  

Python有哪些黑魔法

说到python黑魔法,必然要提到python的第三方协程库gevent的底层实现——greenlet。

greenlet直接在内存层面,通过保存和替换Python进程的运行栈来实现不同协程的切换。

这个切换对于python解释器是透明的,如果python解释器对环境有感知的话,则每当协程切换的时候,它的感觉可能类似一个人前一秒还在在路上走路,下一秒突然自己又出现在了地铁上。

对于普通python用户而言,直接操作python的运行时栈,这就是在刀尖上跳舞有木有,这要求对内存的操作100%精确,任何错误都可能导致python进程崩溃!

作者又是如何又是如何来保证正确性呢?除了要熟悉python、操作系统、编译器等等的底层机制,明确设计方案,还需要对不同的系统以及硬件环境做对应的

适配工作。我们在使用python的时候,在不同的系统或者硬件下感觉都一样,那是因为python本身为我们屏蔽了底层细节,在做这种python底层

hack的事情的时候,显然就没那么轻松了。

举个例子,由于CPU有很多种,例如i386、x86_64、arm等等,每种CPU的设计不尽相同,于是作者为每种CPU写了对应的汇编操作指令来完成栈的保存和替换,这些操作都是与操作系统和硬件高度绑定的。

虽然greenlet的实现这么bt,但就是有人做到了,加上gevent的封装,用起来比python自带协程好用太多。

我想任何对python比较熟悉的童鞋,在初次接触gevent的时候,都会好奇它是如何做到的,在进一步了解其底层greenlet实现机理之后,无不惊叹其鬼斧神工。

这种事情就是那种,别人不说,你可能永远不会想到的事情。

转载

40.少有人知的 Python“重试机制”

为了避免由于一些网络或其他不可控因素,而引起的功能性问题。比如在发送请求时,会因为网络不稳定,往往会有请求超时的问题。

这种情况下,我们通常会在代码中加入重试的代码。重试的代码本身不难实现,但如何写得优雅、易用,是我们要考虑的问题。

这里要给大家介绍的是一个第三方库 - Tenacity ,它实现了几乎我们可以使用到的所有重试场景,比如:

在使用它之前 ,先要安装它

无条件重试,重试之间无间隔

无条件重试,但是在重试之前要等待 2 秒

只重试7 次

重试 10 秒后不再重试

或者上面两个条件满足一个就结束重试

在出现特定错误/异常(比如请求超时)的情况下,再进行重试

在满足自定义条件时,再进行重试。

如下示例,当 test_retry 函数返回值为 False 时,再进行重试

如果想对一个异常进行重试,但是最多重试3次。

下面这个代码是无效的,因为它会一直重试,重试三次的限制不会生效,因为它的条件是有顺序的,在前面的条件会先被走到,就永远走不到后面的条件。

如果你把 stop_after_attempt 写到前边,就没有问题了。

当出现异常后,tenacity 会进行重试,若重试后还是失败,默认情况下,往上抛出的异常会变成 RetryError,而不是最根本的原因。

因此可以加一个参数( reraise=True ),使得当重试失败后,往外抛出的异常还是原来的那个。

当最后一次重试失败后,可以执行一个回调函数

输出如下

摘自黑魔法手册

Python 有什么奇技淫巧

我复制 的,仅供参考,版权归原作者:

1. 元类(metaclass)

PyPy的源码里有个pair和extendabletype

"""

Two magic tricks for classes:

class X:

__metaclass__ = extendabletype

...

# in some other file...

class __extend__(X):

... # and here you can add new methods and class attributes to X

Mostly useful together with the second trick, which lets you build

methods whose 'self' is a pair of objects instead of just one:

class __extend__(pairtype(X, Y)):

attribute = 42

def method((x, y), other, arguments):

...

pair(x, y).attribute

pair(x, y).method(other, arguments)

This finds methods and class attributes based on the actual

class of both objects that go into the pair(), with the usual

rules of method/attribute overriding in (pairs of) subclasses.

For more information, see test_pairtype.

"""

class extendabletype(type):

"""A type with a syntax trick: 'class __extend__(t)' actually extends

the definition of 't' instead of creating a new subclass."""

def __new__(cls, name, bases, dict):

if name == '__extend__':

for cls in bases:

for key, value in dict.items():

if key == '__module__':

continue

# XXX do we need to provide something more for pickling?

setattr(cls, key, value)

return None

else:

return super(extendabletype, cls).__new__(cls, name, bases, dict)

def pair(a, b):

"""Return a pair object."""

tp = pairtype(a.__class__, b.__class__)

return tp((a, b)) # tp is a subclass of tuple

pairtypecache = {}

def pairtype(cls1, cls2):

"""type(pair(a,b)) is pairtype(a.__class__, b.__class__)."""

try:

pair = pairtypecache[cls1, cls2]

except KeyError:

name = 'pairtype(%s, %s)' % (cls1.__name__, cls2.__name__)

bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__]

bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__]

bases = tuple(bases1 + bases2) or (tuple,) # 'tuple': ultimate base

pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {})

return pair

先说extendabletype。嘛 其实注释已经说得听明白了,就是一个C#里面的partial class的Python实现。

然后是pair和pairtype。pairtype就是根据两个类创建一个新的类,这个类继承自使用这两个类的基类构造的pairtype(有点绕……)或者tuple。

有啥用呢?可以拿来实现multimethod。

class __extend__(pairtype(int, int)):

def foo((x, y)):

print 'int-int: %s-%s' % (x, y)

class __extend__(pairtype(bool, bool)):

def bar((x, y)):

print 'bool-bool: %s-%s' % (x, y)

pair(False, True).foo() # prints 'int-int: False, True'

pair(123, True).foo() # prints 'int-int: 123, True'

pair(False, True).bar() # prints 'bool-bool: False, True'

pair(123, True).bar() # Oops, no such method

好像这个例子里元类只是个打辅助的角色,好玩的都在那个pair里……

再换一个。

class GameObjectMeta(type):

def __new__(mcls, clsname, bases, _dict):

for k, v in _dict.items():

if isinstance(v, (list, set)):

_dict[k] = tuple(v) # mutable obj not allowed

cls = type.__new__(mcls, clsname, bases, _dict)

all_gameobjects.add(cls)

for b in bases:

game_objects_hierarchy.add((b, cls))

return cls

@staticmethod

def _dump_gameobject_hierarchy():

with open('/dev/shm/gomap.dot', 'w') as f:

f.write('digraph {nrankdir=LR;n')

f.write('n'.join([

'"%s" - "%s";' % (a.__name__, b.__name__)

for a, b in game_objects_hierarchy

]))

f.write('}')

def __setattr__(cls, field, v):

type.__setattr__(cls, field, v)

if field in ('ui_meta', ):

return

log.warning('SetAttr: %s.%s = %s' % (cls.__name__, field, repr(v)))

这个是从我写的三国杀游戏中提取的一段代码(点我签名上的链接)。大意就是把class上所有可变的容器都换成不可变的,然后记录下继承关系。

曾经被这个问题坑过,class上的值是全局共享的,逻辑代码一不小心修改了class上的值,单机测试的时候是测不出来的,然后放到线上……就悲剧了……当时绞尽脑汁没有想到是这个问题硬生生的回滚了……发现了问题之后就加上了这个东西,不允许修改class上的东西。

记录下继承关系是为了画类图。

还有就是常用的做数据注入

metadata = {}

def gen_metafunc(_for):

def metafunc(clsname, bases, _dict):

meta_for = getattr(_for, clsname)

meta_for.ui_meta = UIMetaDescriptor()

if meta_for in metadata:

raise Exception('%s ui_meta redefinition!' % meta_for)

metadata[meta_for] = _dict

return metafunc

from gamepack.thb import characters

__metaclass__ = gen_metafunc(characters.sakuya)

class Sakuya:

# 于是这个就不是类了, 而是作为数据存到了metadata这个dict里

char_name = u'十六夜咲夜'

port_image = 'thb-portrait-sakuya'

figure_image = 'thb-figure-sakuya'

miss_sound_effect = 'thb-cv-sakuya_miss'

description = (

u'|DB完全潇洒的PAD长 十六夜咲夜 体力:4|rnn'

u'|G月时计|r:|B锁定技|r,准备阶段开始时,你执行一个额外的出牌阶段。nn'

u'|G飞刀|r:你可以将一张装备牌当【弹幕】使用或打出。按此法使用的【弹幕】无距离限制。nn'

u'|DB(画师:小D@星の妄想乡,CV:VV)|r'

)

Ruby党不要喷,我知道你们可以做的更优雅……

2. Python沙盒逃逸

刷新三观的Python代码

3. PEP302 New Import Hook

最近在把刚才提到的纯Python游戏向Unity引擎上移植。

玩过Unity的就会知道,Unity的游戏的资源都是打包在一起的,没有单独的文件,Python解释器就不高兴了……于是写了import hook,用Unity提供的API来读py文件。

# -*- coding: utf-8 -*-

# -- stdlib --

import imp

import sys

# -- third party --

# -- own --

from clr import UnityEngine, WarpGateController

# -- code --

class UnityResourceImporter(object):

known_builtin = (

'sys',

'imp',

'cStringIO',

'gevent_core',

'gevent_ares',

'gevent_util',

'gevent_semaphore',

'msgpack_packer',

'msgpack_unpacker',

'UnityEngine',

)

def __init__(self, bases, unity_loader):

self.bases = bases

self.last_fullname = ''

self.last_text = ''

self.last_ispkg = False

self.unity_load = unity_loader

def find_module(self, fullname, path=None):

if fullname in sys.modules:

return self

head = fullname.split('.')[0]

if head in self.known_builtin:

return None

rst = self.do_load_module(fullname)

if rst:

self.last_text, self.last_ispkg = rst

self.last_fullname = fullname

return self

else:

return None

def load_module(self, fullname):

if fullname in sys.modules:

return sys.modules[fullname]

if fullname != self.last_fullname:

self.find_module(fullname)

try:

code = self.last_text

ispkg = self.last_ispkg

mod = sys.modules.setdefault(fullname, imp.new_module(fullname))

mod.__file__ = "UnityResource: %s" % fullname

mod.__loader__ = self

if ispkg:

mod.__path__ = []

mod.__package__ = fullname

else:

mod.__package__ = fullname.rpartition('.')[0]

co = compile(code, mod.__file__, 'exec')

exec(co, mod.__dict__)

return mod

except Exception as e:

UnityEngine.Debug.LogError('Error importing %s %s' % (fullname, e))

raise ImportError(e)

def do_load_module(self, fullname):

fn = fullname.replace('.', '/')

asset = self.try_load(fn + '.py')

if asset is not None:

return asset, False

asset = self.try_load(fn + '/__init__.py')

if asset is not None:

return asset, True

def try_load(self, filename):

for b in self.bases:

asset = self.unity_load(b + filename)

if asset is not None:

return asset

return None

sys.meta_path.append(UnityResourceImporter([

'Python/THBattle/',

'Python/Site/',

'Python/Stdlib/',

], WarpGateController.GetTextAsset))

需要的extension module都静态编译到解释器里了,所以没考虑。

4. 可以批量执行操作的list

class BatchList(list):

def __getattribute__(self, name):

try:

list_attr = list.__getattribute__(self, name)

return list_attr

except AttributeError:

pass

return list.__getattribute__(self, '__class__')(

getattr(i, name) for i in self

)

def __call__(self, *a, **k):

return list.__getattribute__(self, '__class__')(

f(*a, **k) for f in self

)

class Foo(object):

def __init__(self, v):

self.value = v

def foo(self):

print 'Foo!', self.value

foo = Foo(1)

foo.foo() # Foo! 1

foos = BatchList(Foo(i) for i in xrange(10))

foos.value # BatchList([0, 1, 2, 3, ..., 9])

foos.foo() # 你能猜到的

这个其实不算很黑魔法了,只是感觉很好用也有些危险,所以放上来。

暂时就想到这么多了,以后发现了再补。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。