AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

论 Python 与设计模式 by 赖勇浩

发布者 pattern
发布于 1443574192246  浏览 8900 关键词 Python, 设计模式 
分享到

第1页

+
 

论 Python 与设计模式 

赖勇浩(http://laiyonghao.com)
  2013-­‐12-­‐8
  珠海
 



第2页

+
设  计模式? 



第3页

+
自  我介绍 

n
 赖勇浩
  n
 从业 8 年多,主要编程语言是 

Python
  n
 game
 -­‐>
 webgame
 -­‐>
 web
  n
 常在珠三角技术沙龙出没
  n
 http://laiyonghao.com
 



3
 



第4页

+
P  yCon
 的老朋友 



4
 



第5页

+

好,正式开始吧! 



5
 



第6页

+
先  热热场子…… 

n
 写 Python
 代码赚钱的,有没有?
 



6
 



第7页

+
先  热热场子…… 

n
 写 Python
 代码赚钱的,有没有?
  n
 写 Python 超过 1 年的,有没有?
 



7
 



第8页

+
再  热热场子…… 

n
 读过《设计模式——可复用面向对 象软件的基础》这本书的有没有?
 



8
 



第9页

+
再  热热场子…… 

n
 读过《设计模式——可复用面向对 象软件的基础》这本书的有没有?
 

n
 读过《Head
 First 设计模式》 的有没有?
 



9
 



第10页

10
 

一个观点 



第11页

+
 

我也希望是这样…… 

但事实是…… 



11
 



第12页

+
先  看事实:工厂函数(方法) 



int(…)
 

float(…)
 

type(name,
 bases,
 dict)
  >>>
 class
 X(object):
  ...
 
 
 
 
 a
 =
 1
  ...
  >>>
 X
 =
 type('X',
  (object,),
 dict(a=1))
 

collections.namedtuple() 



datatime.fromtimestamp(…)
  Decimal.from_float(…)
  Fraction.from_float(…)
  Fraction.from_decimal(…) 



第13页

+
先  看事实:享元(FlyWeight) 

>>>
 i
 =
 10
  >>>
 j
 =
 5
 +
 5
  >>>
 id(i)
  140479275503872
  >>>
 id(j)
  140479275503872
  >>>
 a
 =
 'ab'
  >>>
 b
 =
 'a'
 +
 'b'
  >>>
 id(a)
 ==
 id(b)
  True
 



13
 



第14页

+
先  看事实:享元(FlyWeight) 



14
 



>>>
 i
 =
 10
  >>>
 j
 =
 5
 +
 5
  >>>
 id(i)
  140479275503872
  >>>
 id(j)
  140479275503872
  >>>
 a
 =
 'ab'
  >>>
 b
 =
 'a'
 +
 'b'
  >>>
 id(a)
 ==
 id(b)
  True
 



>>>
 a
 =
 a
 *
 10
  >>>
 intern(a)
  'abababababababababab'
  >>>
 b
 =
 'abababababababababab’
  >>>
 c
 =
 'abababababababababa'
 +
 'b’
  >>>
 d
 =
 'ab'
 *
 10
  >>>
 id(a)
 ==
 id(b)
 ==
 id(c)
 ==
  id(d)
  True
 



第15页

+
先  看事实:适配器 



15
 



import
 SocketServer
 

class
 ThreadedTCPServer(SocketServer.ThreadingMixIn,
  SocketServer.TCPServer):
 


 
 
 
 pass
 

 



第16页

+
先  看事实:代理模式 



16
 



>>>
 import
 weakref
  >>>
 class
 A(object):pass
  ...
 
  >>>
 a
 =
 A()
  >>>
 a.attr
 =
 1
  >>>
 a.attr
  1
  
 



>>>
 a1
 =
 weakref.proxy(a)
  >>>
 a1.attr
  1
  >>>
 a1
  <weakproxy
 at
 0x10dc375d0
  to
 A
 at
 0x10dc3a410>
 



第17页

+
先  看事实:模板方法 



17
 



import
 SocketServer
  class
 MyTCPHandler(SocketServer.BaseRequestHandler):
  
 
 
 
 def
 handle(self):
  
 
 
 
 
 
 
 
 self.data
 =
 self.request.recv(1024).strip()
  
 
 
 
 
 
 
 
 print
 "{}
  wrote:".format(self.client_address[0])
  
 
 
 
 
 
 
 
 print
 self.data
  
 
 
 
 
 
 
 
 self.request.sendall(self.data.upper())
 



第18页

+
先  看事实:模板方法 

From
 abc
 import
 ABCMeta
  class
 C:
  
 
 
 
 __metaclass__
 =
 ABCMeta
  
 
 
 
 @abstractmethod
  
 
 
 
 def
 my_abstract_method(self,
 ...):
  
 
 
 
 
 
 
 
 ... 



18
 



第19页

+
所  以,真相是…… 

n
 标准库都在用……
  n
 标准库都推荐用……
  n
 怎么可以说不需要?!
 



19
 



第20页

20
 

+
 所
  以我们不是不需要模式…… 

而是要 Pythonic 的模式实现…… 



第21页

+
不   Pythonic 的设计模式:单例 



21
 



class
 Singleton(object):
 
 
  
 
 
 
 def
 __new__(cls,
 *args,
 **kw):
 
 
  
 
 
 
 
 
 
 
 if
 not
 hasattr(cls,
 '_instance'):
 
 
  
 
 
 
 
 
 
 
 
 
 
 
 orig
 =
 super(Singleton,
 cls)
 
 
  
 
 
 
 
 
 
 
 
 
 
 
 cls._instance
 =
 orig.__new__(cls,
 *args,
  **kw)
 
 
  
 
 
 
 
 
 
 
 return
 cls._instance
  



第22页

+
单  例的三个需求: 

n
 只能有一个实例;
  n
 它必须自行创建这个实例;
  n
 它必须自行向整个系统提供这个

实例。
 



22
 



第23页

+
单  例遇上并行 

class
 Singleton(object):
  
 
 
 
 objs
 
 =
 {}
  
 
 
 
 objs_locker
 =
 
 threading.Lock()
  
 
 
 
 def
 __new__(cls,
 *args,
 **kv):
  
 
 
 
 
 
 
 
 if
 cls
 in
 cls.objs:
  
 
 
 
 
 
 
 
 
 
 
 
 return
 cls.objs[cls]
 



23
 



第24页

+
单  例遇上并行 


 
 
 
 
 
 
 
 cls.objs_locker.acquire()
  
 
 
 
 
 
 
 
 try:
  
 
 
 
 
 
 
 
 
 
 
 
 if
 cls
 in
 cls.objs:
  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 return
 cls.objs[cls]
  
 
 
 
 
 
 
 
 
 
 
 
 cls.objs[cls]
 =
 object.__new__(cls)
  
 
 
 
 
 
 
 
 finally:
  
 
 
 
 
 
 
 
 
 
 
 
 cls.objs_locker.release() 



24
 



第25页

+
P  ythonic
 的设计模式:单例 



25
 



n
 重新审视 Python 的语法元素,尽量利用已有基础设施。
 

n
 模块
 

n
 所有的变量都会绑定到模块;  n
 模块只初始化一次;
  n
 import
 机制是线程安全的(保证了在并发状态下模块也只有一个实

例); 

n
 惯用法:
 

n
 文件名首字母大写,如 Moon.py
  n
 __all__ 



第26页

+
不   Pythonic 的设计模式:装饰器 



26
 



第27页

+
代  码大概是这样的 

class
 darkroast(Beverage):
  
 
 def
 cost(self):return
 0.99
  …
  class
 Whip(Beverage):
 

def
 __init__(self,
 beverage):
  self._beverage
 =
 beverage
  
 

def
 cost(self):
  return
 self._beverage.cost()
 +
 0.1
 

print
 Whip(Mocha(darkroast())).cost()
 



27
 



第28页

+
P  ythonic 的设计模式:装饰器 

def
 beverage(cost):
  
 
 def
 _(orig
 =
 0.0):
  
 
 
 
 return
 orig
 +
 cost
  
 
 return
 _
  darkroast
 =
 beverage(0.99)
  whip
 =
 beverage(0.1)
  mocha
 =
 beverage(0.2)
  print
 whip(mocha(darkroast()))
 



28
 



第29页

+
其  它设计模式:Borg(MonoState) 



29
 



n
 保持对象的唯一性并不重要,只 要共享状态就行
 

n
 Alex
 Martelli
 

n
 http:// code.activestate.com/ recipes/66531/
 



第30页

+
其  它设计模式:Borg(MonoState) 



30
 



class
 Borg(object):
 
 
  
 
 
 
 _state
 =
 {}
 
 
  
 
 
 
 def
 __new__(cls,
 *args,
 **kw):
 
 
  
 
 
 
 
 
 
 
 ob
 =
 super(Borg,
 cls).__new__(cls,
 *args,
  **kw)
 
 
  
 
 
 
 
 
 
 
 ob.__dict__
 =
 cls._state
 
 
  
 
 
 
 
 
 
 
 return
 ob
  



第31页

+
动  态语言特有的设计模式:mixin 



31
 



n
 动态地改变实例的类型的基类,在不修改生成实例过程的情况下, 给实例增加(改变)功能。可用以实现插件框架。
 

class
 Bird(object):pass
  bird
 =
 Bird()
  class
 FlyMixin:
  
 
 def
 fly(self):print
 'I
 can
 fly.'
  bird.__class__.__bases__
 +=
 (FlyMixin,
 )
  bird.fly()
 



第32页

+
动  态语言特有的模式:duck
 typing  32
 

n
 一个对象有效的语义,不是由继承自特定的类或实现特定的接口, 而是由当前方法和属性的集合决定。
 

n
 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子, 那么这只鸟就可以被称为鸭子。(James
 Whitcomb
 Riley)
 

n
 干掉模板方法?
 

n
 不,模板方法是想要保证子类实现接口 



第33页

+
利  用设计模式提供更好的接口 



33
 



n
 getopt
  n
 optparse
  n
 argparse
 

n
 docopt 



n
 Command-­‐line
 interface
  description
 language
 

n
 define
 interface
 for
 your
  command-­‐line
 app,
 and
 

n
 automatically
 generate
  parser
 for
 it.
 

n
 解释器模式 



第34页

+
d  ocopt 



34
 



第35页

+
解  释器模式的应用 

n
 GM 指令
  player
 0
 money
 10000
  player
 0
 attack
 10000
  monster
 0
 die
  scene
 monsters
 die
 

n
 过场剧情脚本
  monster
 0
 spawn
 0,0
  monster
 0
 moveto
 0,-­‐10
  monster
 0
 attack
  monster
 0
 moveto
 0,0 



35
 



第36页

+

Q&A 

mail@laiyonghao.com
   



36
 



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。