sample
Python Multiprocessing Example How To Use Signal Driven Programming In Applications
闭包、装饰器、生成器、协程、多进程
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
三种方式实现
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,init和call,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