python callable对象_python面对对象编程----------7:callable(类调用)与context(上下文)...

一:callables

callables使类实例能够像函数一样被调用

如果类需要一个函数型接口这时用callable,最好继承自abc.Callable,这样有些检查机制并且一看就知道此类的目的是callable对象

如果类需要有‘记忆’功能,使用callable是非常方便的相对于函数而言,callable语法什么的就要复杂多了,这也是其主要的缺点:

def x(args):

body

转化为callable对象:

class X(collections.abc.callable):

def __call__(self, args):

body

x= X()

1:计算x^y

1 import collections.abc #注,完全可以不引入cleection.abc,引入是为了能够做一些错误检查

2 classPower1( collections.abc.Callable ):3 def __call__( self, x, n ):4 p= 1

5 for i inrange(n):6 p *=x7 returnp8

9 power=Power1()10 >>> power( 2, 0 ) #像函数一样调用实例

11 1

12 >>> power( 2, 1)13 2

14 >>> power( 2, 2)15 4

16 >>> power( 2, 10)17 1024

18

19 #提升性能:上面是O(n),用递归改进为O(logn)

20 classPower4( abc.Callable ):21 def __call__( self, x, n ):22 if n ==0:23 return 1

24 elif n % 2 == 1:25 return self.__call__(x, n-1)*x26 else:27 t= self.__call__(x, n//2)28 return t*t29

30 pow4=Power4()31

32 #再次提升性能,使用记忆功能【注:可以{(2,4):16,... }

33 classPower5( collections.abc.Callable ):34 def __init__( self ):35 self.memo ={}36 def __call__( self, x, n ):37 if (x,n) not inself.memo:38 if n ==0:39 self.memo[x,n]= 1

40 elif n % 2 == 1:41 self.memo[x,n]= self.__call__(x, n-1) *x42 elif n % 2 ==0:43 t= self.__call__(x, n//2)44 self.memo[x,n]= t*t45 else:46 raise Exception("Logic Error")47 returnself.memo[x,n]48

49 pow5=Power5()50

51 #再次改进,python库自带了一个记忆装饰器,可以使用这个从而不不用自定义callable对象

52 from functools importlru_cache53 @lru_cache(None)54 defpow6( x, n ):55 if n ==0:56 return 1

57 elif n % 2 == 1:58 return pow6(x, n-1)*x59 else:60 t= pow6(x, n//2)61 return t*t62 #Previous requests are stored in a memoization cache. The requests are

63 #tracked in the cache, and the size is limited. The idea behind an LRU cache is that

64 #the most recently made requests are kept and the least recently made requests are quietly purged.

callable试例1

2:赌注翻倍:综合运用callables,输家翻倍赌注政策:每输一次后赌注就加倍直到赢了后回归原本赌注

1 classBettingMartingale( BettingStrategy ):2 def __init__( self ):3 self._win=04 self._loss=05 self.stage= 1

6 @property7 defwin(self):8 returnself._win9 @win.setter10 defwin(self, value):11 self._win =value12 self.stage= 1

13 @property14 defloss(self):15 returnself._loss16 @loss.setter17 defloss(self, value):18 self._loss =value19 self.stage *= 2

20

21 def __call__( self ):22 returnself.stage23

24 >>> bet=BettingMartingale()25 >>>bet()26 1

27 >>> bet.win += 1

28 >>>bet()29 1

30 >>> bet.loss += 1

31 >>>bet()32 2

33

34 #property的使用使类的定义显得冗杂,实际上我们只关心setters,所以我们用__setattr__来改进上述版本

35 classBettingMartingale2( BettingStrategy ):36 def __init__( self ):37 self.win=038 self.loss=039 self.stage= 1

40 def __setattr__( self, name, value ):41 if name == 'win':42 self.stage = 1

43 elif name == 'loss':44 self.stage *= 2

45 super().__setattr__( name, value )46 def __call__( self ):47 return self.stage

callable示例2

二:context

A context is generally used to acquire/release, open/close, and lock/unlock types of operation pairs.

Most of the examples are file I/O related, and most of the file-like objects in Python are already proper context managers.

1:一些context

1:最常见的是用在文件的,with语句创建

2:decimal context:decimal是一个模块,常用于一些对于精度要求比较严格的计算,其本身运行在一个context中,通过改context可以对全局的计算产生影响

3:还有一些context,主要都是用于类文件的操作

2:构造context(第八章会详细讲解构造context)

context最主要的是有__enter__()与__exit__()方法,分别在with语句开始和结束时调用

抛出的问题都会以traceback参数传递到__exit__()函数中,应该做相应处理。

例子:错误处理context:在打开文件时做备份,若处理完文件没出问题就删除备份,若出了问题就使用备份来恢复原文件

1 importos2 classUpdating:3 def __init__( self, filename ):4 self.filename=filename5 def __enter__( self ): #做文件备份

6 try:7 self.previous= self.filename+"copy"

8 os.rename( self.filename, self.previous )9 exceptFileNotFoundError:10 #Never existed, no previous copy

11 self.previous=None12

13 def __exit__( self, exc_type, exc_value, traceback ): #14 if exc_type is notNone:15 try:16 os.rename( self.filename, self.filename+ "error")17 exceptFileNotFoundError:18 pass #Never even got created?

19 ifself.previous:20 os.rename( self.previous, self.filename ) #用备份文件恢复原文件

21

22 with Updating( "some_file"):23 with open( "some_file", "w") as target:24 process( target )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值