zoukankan      html  css  js  c++  java
  • 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     class Power1( collections.abc.Callable ):
     3     def __call__( self, x, n ):
     4         p= 1
     5         for i in range(n):
     6             p *= x
     7         return p
     8 
     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 class Power4( 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)*x
    26         else:
    27             t= self.__call__(x, n//2)
    28             return t*t
    29 
    30 pow4= Power4()
    31 
    32 # 再次提升性能,使用记忆功能【注:可以{(2,4):16,... }
    33 class Power5( collections.abc.Callable ):
    34     def __init__( self ):
    35         self.memo = {}
    36     def __call__( self, x, n ):
    37         if (x,n) not in self.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) * x
    42             elif n % 2 == 0:
    43                 t= self.__call__(x, n//2)
    44                 self.memo[x,n]= t*t
    45             else:
    46                 raise Exception("Logic Error")
    47         return self.memo[x,n]
    48 
    49 pow5= Power5()
    50 
    51 # 再次改进,python库自带了一个记忆装饰器,可以使用这个从而不不用自定义callable对象
    52 from functools import lru_cache
    53 @lru_cache(None)
    54 def pow6( x, n ):
    55     if n == 0:
    56         return 1
    57     elif n % 2 == 1:
    58         return pow6(x, n-1)*x
    59     else:
    60         t= pow6(x, n//2)
    61         return t*t
    62 # 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 class BettingMartingale( BettingStrategy ):
     2     def __init__( self ):
     3         self._win= 0
     4         self._loss= 0
     5         self.stage= 1
     6     @property
     7     def win(self):
     8         return self._win
     9     @win.setter
    10     def win(self, value):
    11         self._win = value
    12         self.stage= 1
    13     @property
    14     def loss(self):
    15         return self._loss
    16     @loss.setter
    17     def loss(self, value):
    18         self._loss = value
    19         self.stage *= 2
    20 
    21     def __call__( self ):
    22         return self.stage
    23 
    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 class BettingMartingale2( BettingStrategy ):
    36     def __init__( self ):
    37         self.win= 0
    38         self.loss= 0
    39         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 import os
     2 class Updating:
     3     def __init__( self, filename ):
     4         self.filename= filename
     5     def __enter__( self ):                  #做文件备份
     6         try:
     7             self.previous= self.filename+" copy"
     8             os.rename( self.filename, self.previous )
     9         except FileNotFoundError:
    10             # Never existed, no previous copy
    11             self.previous= None
    12 
    13     def __exit__( self, exc_type, exc_value, traceback ):       #
    14         if exc_type is not None:
    15             try:
    16                 os.rename( self.filename, self.filename+ " error" )
    17             except FileNotFoundError:
    18                 pass # Never even got created?
    19             if self.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 )


  • 相关阅读:
    PetShop4.0学习笔记[01]:订单处理[01]——多线程程序结构
    PetShop4.0学习笔记——使用命名空间
    PetShop 4.0学习笔记:消息队列MSMQ
    petshop4 MSDTC 不可用解决
    经典工具软件备份
    ASP.NET知识点(三):购物车与收藏蓝的实现[Profile]
    PetShop 4.0知识点:加密和解密Web.config文件的配置节
    PetShop 4.0知识点:base 关键字用于从派生类中访问基类的成员
    从Word,Excel中提取Flash
    线性结构
  • 原文地址:https://www.cnblogs.com/pengsixiong/p/5382982.html
Copyright © 2011-2022 走看看