sample

Python函数进阶:闭包、装饰器、生成器、协程

理解Python的协程(Coroutine)

Python Multiprocessing Example How To Use Signal Driven Programming In Applications

Django Signals 信号

闭包、装饰器、生成器、协程、多进程

mixin类似java中的implement, PHP中的trait, 定义的是接口,而非类

协程的特点在于是一个线程执行,那和多线程比,协程有何优势?

最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

因为协程是一个线程执行,那怎么利用多核CPU呢?
最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

===闭包===
def countdown(n):
    def next():
        nonlocal n    # 声明n为next()函数外部的变量
        r = n
        n -= 1
        return r
    return next
     
next = countdown(10)
while True:
    v = next()
    if not v: break


===装饰器===
# 定义装饰器函数
def print_result(func):
    def callf(*args, **kwargs):
        r = func(*args, **kwargs)
        print('Do something with return: %d.' %r)
        return r+7
    return callf
     
# 用@装饰原函数
@print_result
def square(x):
    return x*x

# 多个装饰器
@dec1
@dec2
@dec3
def square(x):
    pass
     
square = dec1(dec2(dec3(square)))

# 装饰器参数
@eventhandler('BUTTON')
def handle_button(msg):
    pass
     
@eventhandler('RESET')
def handle_reset(msg):
    pass

# 事件处理程序装饰器
event_handlers = {}
def eventhandler(event):
    def register_function(f):
        event_handlers[event] = f
        return f
    return register_function
     
@eventhandler('BUTTON')
def handle_button(msg):
    pass

===生成器===
# 定义生成器
def countdown(n):
    print('Start counting')
    while n > 0:
        yield n
        n -= 1

for i in countdown(3):
    print(i)

# 生成器实现管道功能
# 输出函数只管输出
def tail(f):
    f.seek(0, os.SEEK_END)
    while True:
        line = f.readline()
        if not line:
            time.sleep(1)
            continue
             
        yield line
         
# 输入函数只管处理输入内容
def grep(linegtr, searchtxt):
    for line in linegtr:
        if searchtxt in line:
            yield line        
         
# 下面是用户使用代码
f = open('log.txt')
logtxt = tail(f)                   # logtxt是一个生成器对象,每次
result = grep(logtxt, 'Jerry')     # result也是一个生成器对象
for line in result:
    print(line)

# 手动关闭生成器
c.close()

# yield语句上捕获GeteratorExit异常
def countdown(n):
    try:
        while n > 0:
            yield n
            n -= 1
    except GeneratorExit:
        print('The current n is %d' %n)


===声明式编程===
lines = open('stationery.txt')
fields = (line.split(',') for lien in lines)
print(sum( float(f[1]) * float(f[2]) for f in fields ))

sum(price*qty for price,qty in
      cursor.execute('select price, qty from stationery')
          if price*qty >= 100)

===协程===
import asyncio

async def compute(x, y):
    print("Compute %s + %s ..." % (x, y))
    await asyncio.sleep(1.0)
    return x + y

async def print_sum(x, y):
    result = await compute(x, y)
    print("%s + %s = %s" % (x, y, result))

loop = asyncio.get_event_loop()
loop.run_until_complete(print_sum(1, 2))
print("end")
loop.close()

输出:
Compute 1 + 2 ...
1 + 2 = 3
end


import asyncio
future = asyncio.Future()

async def coro1():
    print("wait 1 second")
    await asyncio.sleep(1)
    print("set_result")
    future.set_result('data')

async def coro2():
    result = await future
    print(result)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([
    coro1()
    coro2()
]))
loop.close()

输出:
wait 1 second
set_result
data

===多进程===
import multiprocessing

print("Number of cpu : ", multiprocessing.cpu_count())
from multiprocessing import Process

def print_func(continent='Asia'):
    print('The name of continent is : ', continent)

if __name__ == "__main__":
    names = ['America', 'Europe', 'Africa']
    procs = []
    proc = Process(target=print_func)
    procs.append(proc)
    proc.start()

    for name in names:
        proc = Process(target=print_func, args=(name,))
        procs.append(proc)
        proc.start()

    for proc in procs:
        proc.join()


进程池:
from multiprocessing import Pool

import time

work = (["A", 5], ["B", 2], ["C", 1], ["D", 3])

def work_log(work_data):
    print(" Process %s waiting %s seconds" % (work_data[0], work_data[1]))
    time.sleep(int(work_data[1]))
    print(" Process %s Finished." % work_data[0])

def pool_handler():
    p = Pool(2)
    p.map(work_log, work)

if __name__ == '__main__':
    pool_handler()

元类metaclass

一旦你把一个类型 MyClass 的 metaclass 设置成 MyMeta,MyClass 就不再由原生的 type创建,而是会调用 MyMeta 的__call__运算符重载。

class = type(classname, superclasses, attributedict)
这里等号右边的type(classname, superclasses, attributedict),就是 type 的__call__运算符重载,它会进一步调用:
type.__new__(typeclass, classname, superclasses, attributedict)
type.__init__(class, classname, superclasses, attributedict)
----------------------------------

class = type(classname, superclasses, attributedict) 
# 变为了
class = MyMeta(classname, superclasses, attributedict)

class MyMeta(type):
    def __new__(cls, *args, **kwargs):
        print('===>MyMeta.__new__')
        print(cls.__name__)
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, classname, superclasses, attributedict):
        super().__init__(classname, superclasses, attributedict)
        print('===>MyMeta.__init__')
        print(self.__name__)
        print(attributedict)
        print(self.tag)

    def __call__(self, *args, **kwargs):
        print('===>MyMeta.__call__')
        obj = self.__new__(self, *args, **kwargs)
        self.__init__(self, *args, **kwargs)
        return obj
    
class Foo(object, metaclass=MyMeta):
    tag = '!Foo'

    def __new__(cls, *args, **kwargs):
        print('===>Foo.__new__')
        return super().__new__(cls)

    def __init__(self, name):
        print('===>Foo.__init__')
        self.name = name

print('test start')
foo = Foo('test')
print('test end')


元类实现单例
class SingletonMeta(type):
    def __init__(self,*args,**kwargs):
        self.__instance = None    #这是一个私有属性来保存属性,而不会污染Singleton类(其实还是会污染,只是无法直接通过__instance属性访问)
        super().__init__(*args,**kwargs)
        
    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
        return self.__instance


class Singleton(metaclass=SingletonMeta): #在代码执行到这里的时候,元类中的__new__方法和__init__方法其实已经被执行了,而不是在Singleton实例化的时候执行。且仅会执行一次。
    pass


class SubSingleton(metaclass=SingletonMeta):
    pass


s1 = Singleton()
s2 = Singleton()
print(s1 is s2)

ss1 = SubSingleton()
ss2 = SubSingleton()
print(ss1 is ss2)

Python之数据序列化(json、pickle、shelve)


>>> xInstance = X(1, 2, 3) >>> xInstance(1,2) _call_ with (1, 2)

singleton example

SingleTon - a complete guide

SingleTon

三种方式实现
1.Module-level singleTon
2.Classic singleTon
3.Borg SingleTon


1.Module-level:
import 天然支持singleton(All moduels are singleton)

# singleton.py
shared_var = 'variable''

# module1.py
import singletom
print(singletom.shared_var)
singletom.shared_var += '(modified by module1)'

# module2.py
import singletom
print(singletom.shared_var)

Run:
import module1.py
import module2.py

输出:
>>> variable
>>> variable(modified by module1)


2.Classic
class SingletonClass(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(SingletonClass, cls).__new__(cls)
        return cls.instance

class SingletonChild(SingletonClass):
    pass
    
singleton = SingletonClass()
child = SingletonChild()
print(singleton is child)
singleton.variable = 'singleton variable'
print(child.variable)

输出(相同的实例,相同的变量):
True
singleton variable


3.Borg
Borg singleton是python的一种设计模式,允许不同的实例共享相同的变量

class BorgSingleton(object):
    _shared_borg_state = {}

    def __new__(cls, *args, **kwargs):
	    obj = super(BorgSingleton, cls).__new__(cls, *args, **kwargs)
	    obj.__dict__ = cls._shared_borg_state
	    return obj

borg = BorgSingleton()
borg.shared_variable = "Shared Variable"

class ChildBorg(BorgSingleton):
    pass

childBorg = ChildBorg()
print(childBorg is borg)
print(childBorg.shared_variable)

输出:
False
Shareed Variable

_new,initcall,del_

__new__ 是一个静态方法,cls由解释器传值,返回参数
__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

若__new__没有正确返回当前类cls的实例,那__init__是不会被调用的,即使是父类的实例也不行

1. __init__(): 初始化某个类的一个实例。 
2. __call__(): 使实例能够像函数一样被调用(调用__new__和__init__)
3. __main__(): 命令行执行调用, 先调用__init__
4. __str__():  显示字串: str(obj), print(obj), format(obj)
5. __repr__(): 显示对象,便于调试: repr(obj)
6. __del__():  删除实例
7.__getitem__() __setitem__: 调用p['name']

class X(object):
    def __new__(cls,*args, **kwargs):
        print "new %s"%cls
        return object.__new__(cls, *args, **kwargs)

    def __init__(self, a, b, range):
        self.a = a
        self.b = b
        self.range = range
        
    def __main__(self):
        print('command called!')
        
    def __call__(self, a, b):
        self.a = a
        self.b = b
        print('__call__ with ({}, {})'.format(self.a, self.b))
        
    def __str__(self):
        return print('x object')

    def __repr__(self):
        return self.__repr__;
        
    def __del__(self, a, b, range):
        del self.a
        del self.b
        del self.range
        
    def __getitem__(self, key):
        return self.__dict__.get(key)
        
    def __setitem__(self, key, value):
        return self.__dict__.set(key, value)

类变量、实例变量、类方法、实例方法

class Foo:
    class_var = ''                  #类变量,相当于静态变量
    def __init__(self):
        self._age = 0
        self.instance_var = ''      #实例变量
    def __main__(self):             #命令行调用python foo.py
        print('usage command line!')
    @classmethod
    def class_method(cls,parameter):#相当于静态类,cls代表类
        print(cls.instance_var)
        print(class_var)
    @staticmethod
    def statis_method(paramter):
        print(self.instance_var)    #不能访问
        print(class_var)            #不能访问
    def method(self,parameter):     #实例类,self代表当前类实例
        print(Object.class_var)
        print(self,instance_var)
    @property
    def age(self):
        return self._age;
    @age.setter
    def age(self, value):
        if isinstance(value,str):
            self._age = Decimal(value)
        if isinstance(value, Decimal):
            self._age = value
    @age.deleter
    def age(self):
        raise AttributeError("cannot delete attribute")

foo = Foo()
print(foo.age)
foo.age = 12
del foo.age


class A:
    v = 22;
a = A()
a.v = 13
print(A.v)      #22
print(a.v)      #13
del a.v
print(a.v)      #22