• 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 )


  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/pengsixiong/p/5382982.html
Copyright © 2020-2023  润新知