Home >Backend Development >Python Tutorial >Python 有什么奇技淫巧?

Python 有什么奇技淫巧?

WBOY
WBOYOriginal
2016-06-06 16:22:101175browse

0.这个问题虽说是找寻“奇技淫巧”,但其实是想抛砖引玉
1.如果想把自己认为或好玩或强大的python使用技巧拿出来跟大家分享,可否稍微详细的讲解一下

回复内容:

从 Python 2.3 开始,sys 包有一个属性,叫 meta_path 。可以通过给 sys.meta_path 注册一个 finder 对象,改变 import 的行为。甚至可以实现这样的功能:通过 import 来导入一个 json 文件中的数据。

举个例子,有一个 tester.json 文件,里面的内容是:
<code class="language-text">{
    "hello": "world",
    "this": {
        "can": {
            "be": "nested"
        }
    }
}
</code>
更新一个最近发现的技巧,一行代码实现多线程/多进程,来源于python开发者微信公众号。

首先来看下代码:


import urllib2
from multiprocessing.dummy import Pool as ThreadPool

urls = [
'http://www.python.org',
'http://www.python.org/about/',
'http://www.onlamp.com/pub/a/python/2003
]

pool = ThreadPool(4)
results = pool.map(urllib2.urlopen, urls)
pool.close()
pool.join()

对,你没有看错,只要一行代码就可以把普通的任务变成并行任务。不用手动管理线程,一切都由map自动完成。这里演示的是多线程,如果要多进程的话只需把 from multiprocessing.dummy 改成 from multiprocessing ,就是这么任性!

以下为这个库的详细介绍:

在 Python 中有个两个库包含了 map 函数: multiprocessing 和它鲜为人知的子库 multiprocessing.dummy.

这里多扯两句: multiprocessing.dummy? mltiprocessing 库的线程版克隆?这是虾米?即便在 multiprocessing 库的官方文档里关于这一子库也只有一句相关描述。而这句描述译成人话基本就是说:”嘛,有这么个东西,你知道就成.”相信我,这个库被严重低估了!

dummy 是 multiprocessing 模块的完整克隆,唯一的不同在于 multiprocessing 作用于进程,而 dummy 模块作用于线程(因此也包括了 Python 所有常见的多线程限制)。
所以替换使用这两个库异常容易。你可以针对 IO 密集型任务和 CPU 密集型任务来选择不同的库。


原文链接 : http://mp.weixin.qq.com/s?__biz=MzA4MjEyNTA5Mw==&mid=2652563685&idx=2&sn=f563f8913630a4334219ed4a9fa99653&scene=0#wechat_redirect

———————以下为原答案———————————

搜了一下,发现没人说这个。
废话不说,直接上图:
Python 有什么奇技淫巧?

在python中,下滑杠代表上一次运行的结果。不要问我为什么,我也不知道。
这个奇技淫巧是我在查scapy的资料的时候意外发现的,网上关于这个技巧的资料似乎也很少,嗯。(顺便提一下,scapy是个非常强大的库,几乎涵盖了所有网络相关的功能,推荐学习。)

再来说一个吧,关于动态修改代码的。直接上代码:

<code class="language-text"># socket.py
#

import sys

del sys.modules['socket']   # 从内存中删除当前的socket包

import sys
import time
import logging
import types

path = sys.path[0]
sys.path.pop(0)    
    

import socket    # 导入真正的socket包

sys.path.insert(0, path)



# 动态path类方法
def re_class_method(_class, method_name, re_method):
    method = getattr(_class, method_name)
    info = sys.version_info
    if info[0] >= 3:   # py2和py3的语法略有不同,需要做下判断。
        setattr(_class, method_name,
                types.MethodType(lambda *args, **kwds: re_method(method, *args, **kwds), _class))
    else:
        setattr(_class, method_name,
                types.MethodType(lambda *args, **kwds: re_method(method, *args, **kwds), None, _class))

# 动态path实例方法
def re_self_method(self, method_name, re_method):
    method = getattr(self, method_name)
    setattr(self, method_name, types.MethodType(lambda *args, **kwds: re_method(method, *args, **kwds), self, self))


# 需要修改的类方法
def re_accept(old_method, self, *args, **kwds):

    return_value = old_method(self, *args, **kwds)
    #do something
    return return_value


# 需要修改的实例方法
def re_recvfrom(old_method, self, *args, **kwds):

    return_value = old_method(*args, **kwds)
    # do something
    return return_value

# 需要修改的类方法(无返回值)
def re_bind(old_method, self, *args, **kwds):
    re_self_method(self, 'recvfrom', re_recvfrom) #把self实例的recvfrom方法替换成re_recvfrom
    #do something
    old_method(self, *args, **kwds)


setattr(socket.socket, '_list_client_ip', {})  #  绑定类属性(socket不能动态绑定实例属性,只好绑定类属性了)
re_class_method(socket.socket, 'bind', re_bind)  #把socket类的bind方法替换成re_bind
re_class_method(socket.socket, 'accept', re_accept)  #把socket类的accept方法替换成re_accept
</code>
也有一个 Python 的奇技淫巧分享给大家,让 Python 的 2+2=5:

<code class="language-python"><span class="n">In</span> <span class="p">[</span><span class="mi">1</span><span class="p">]:</span> <span class="kn">import</span> <span class="nn">ctypes</span>

<span class="n">In</span> <span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">memmove</span><span class="p">(</span><span class="nb">id</span><span class="p">(</span><span class="mi">4</span><span class="p">),</span> <span class="nb">id</span><span class="p">(</span><span class="mi">5</span><span class="p">),</span> <span class="mi">24</span><span class="p">)</span>
<span class="n">Out</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="mi">15679760</span>

<span class="n">In</span> <span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">2</span>
<span class="n">Out</span><span class="p">[</span><span class="mi">3</span><span class="p">]:</span> <span class="mi">5</span>
</code>
刚好看到个
Python 有什么奇技淫巧? Python 有什么奇技淫巧?来自于 python高级编程 作者是 @董伟明 说明在分享一个准备给公司讲python高级编程的slide 这里还有对应的视频讲解

====================================================================

另外一个感觉就是这个库了ajalt/fuckitpy · GitHub 中间的实现挺厉害的,访问源码逐行加入try: finally Python没有什么奇技淫巧吧。。。Hidden features of Python 这个链接上有很多小例子
比如for else值得说下。不break的话就执行else
<code class="language-python"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">10</span><span class="p">:</span>
        <span class="k">break</span>
    <span class="k">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">'10不在里面!'</span><span class="p">)</span>
</code>
其实 PYC 文件很简单:
<code class="language-text">>>> import dis, marshal
>>> with open('hello.pyc', 'rb') as f:
...     f.seek(8)
...     dis.dis(marshal.load(f))
</code>
昨天刚在 StackOverflow 看到的,break 多层循环:python - Breaking out of nested loops
<code class="language-python"><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
        <span class="k">print</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span>
        <span class="k">if</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span> <span class="o">></span> <span class="mi">50</span><span class="p">:</span>
            <span class="k">break</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">continue</span>  <span class="c"># executed if the loop ended normally (no break)</span>
    <span class="k">break</span>  <span class="c"># executed if 'continue' was skipped (break)</span>
</code>
可配置单例,从tornado学来的
Python 有什么奇技淫巧? Stack Overflow上有一个多人编辑整理的答案,非常全而且经常更新:
Hidden features of Python

收藏这个页面,顺便给我的回答点个赞同啊。 1. 元类(metaclass)
PyPy的源码里有个pair和extendabletype
<code class="language-python"><span class="sd">"""</span>
<span class="sd">Two magic tricks for classes:</span>
<span class="sd">    class X:</span>
<span class="sd">        __metaclass__ = extendabletype</span>
<span class="sd">        ...</span>
<span class="sd">    # in some other file...</span>
<span class="sd">    class __extend__(X):</span>
<span class="sd">        ...      # and here you can add new methods and class attributes to X</span>
<span class="sd">Mostly useful together with the second trick, which lets you build</span>
<span class="sd">methods whose 'self' is a pair of objects instead of just one:</span>
<span class="sd">    class __extend__(pairtype(X, Y)):</span>
<span class="sd">        attribute = 42</span>
<span class="sd">        def method((x, y), other, arguments):</span>
<span class="sd">            ...</span>
<span class="sd">    pair(x, y).attribute</span>
<span class="sd">    pair(x, y).method(other, arguments)</span>
<span class="sd">This finds methods and class attributes based on the actual</span>
<span class="sd">class of both objects that go into the pair(), with the usual</span>
<span class="sd">rules of method/attribute overriding in (pairs of) subclasses.</span>
<span class="sd">For more information, see test_pairtype.</span>
<span class="sd">"""</span>

<span class="k">class</span> <span class="nc">extendabletype</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
    <span class="sd">"""A type with a syntax trick: 'class __extend__(t)' actually extends</span>
<span class="sd">    the definition of 't' instead of creating a new subclass."""</span>
    <span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s">'__extend__'</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">cls</span> <span class="ow">in</span> <span class="n">bases</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                    <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">'__module__'</span><span class="p">:</span>
                        <span class="k">continue</span>
                    <span class="c"># XXX do we need to provide something more for pickling?</span>
                    <span class="nb">setattr</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
            <span class="k">return</span> <span class="bp">None</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="nb">super</span><span class="p">(</span><span class="n">extendabletype</span><span class="p">,</span> <span class="n">cls</span><span class="p">)</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">pair</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
    <span class="sd">"""Return a pair object."""</span>
    <span class="n">tp</span> <span class="o">=</span> <span class="n">pairtype</span><span class="p">(</span><span class="n">a</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">__class__</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">tp</span><span class="p">((</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>   <span class="c"># tp is a subclass of tuple</span>

<span class="n">pairtypecache</span> <span class="o">=</span> <span class="p">{}</span>

<span class="k">def</span> <span class="nf">pairtype</span><span class="p">(</span><span class="n">cls1</span><span class="p">,</span> <span class="n">cls2</span><span class="p">):</span>
    <span class="sd">"""type(pair(a,b)) is pairtype(a.__class__, b.__class__)."""</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">pair</span> <span class="o">=</span> <span class="n">pairtypecache</span><span class="p">[</span><span class="n">cls1</span><span class="p">,</span> <span class="n">cls2</span><span class="p">]</span>
    <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
        <span class="n">name</span> <span class="o">=</span> <span class="s">'pairtype(</span><span class="si">%s</span><span class="s">, </span><span class="si">%s</span><span class="s">)'</span> <span class="o">%</span> <span class="p">(</span><span class="n">cls1</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="n">cls2</span><span class="o">.</span><span class="n">__name__</span><span class="p">)</span>
        <span class="n">bases1</span> <span class="o">=</span> <span class="p">[</span><span class="n">pairtype</span><span class="p">(</span><span class="n">base1</span><span class="p">,</span> <span class="n">cls2</span><span class="p">)</span> <span class="k">for</span> <span class="n">base1</span> <span class="ow">in</span> <span class="n">cls1</span><span class="o">.</span><span class="n">__bases__</span><span class="p">]</span>
        <span class="n">bases2</span> <span class="o">=</span> <span class="p">[</span><span class="n">pairtype</span><span class="p">(</span><span class="n">cls1</span><span class="p">,</span> <span class="n">base2</span><span class="p">)</span> <span class="k">for</span> <span class="n">base2</span> <span class="ow">in</span> <span class="n">cls2</span><span class="o">.</span><span class="n">__bases__</span><span class="p">]</span>
        <span class="n">bases</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">bases1</span> <span class="o">+</span> <span class="n">bases2</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,)</span>  <span class="c"># 'tuple': ultimate base</span>
        <span class="n">pair</span> <span class="o">=</span> <span class="n">pairtypecache</span><span class="p">[</span><span class="n">cls1</span><span class="p">,</span> <span class="n">cls2</span><span class="p">]</span> <span class="o">=</span> <span class="n">extendabletype</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="p">{})</span>
    <span class="k">return</span> <span class="n">pair</span>
</code>
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn