• 如何通过实例方法名字的字符串调用方法?


    需求:
    某项目中,我们的代码使用了三个不同库中的图形类,Circle,Triangle,Rectangle
    他们都有一个获取图形面积的接口(方法)但是接口名字不同,我们实现一个统一获取面积的函数,使用每种方法名进行尝试,调用相应类的接口

    思路:
    1、使用内置函数getattr,通过名称在实例上获取方法对象,然后调用
    2、使用标准库下operator下的methodcaller函数调用

    代码:

    方法一:
    lib1.py:
    
    class Circle(object):
        def __init__(self,r):
            self.r = r
    
        def area(self):
            return self.r ** 2 * 3.14
    
    lib2.py:
    
    class Triangle(object):
        def __init__(self,a,b,c):
            self.a = a
            self.b = b
            self.c = c
    
        def getArea(self):
            a,b,c = self.a,self.b,self.c
            p = (a+b+c)/2
            area = (p * (p -a) * (p - b )*(p - c)) ** 0.5
            return area
    
    lib3.py:
    
    class Rectangle(object):
        def __init__(self,w,h):
            self.w = w
            self.h = h
    
        def get_area(self):
            return self.w * self.h
    
    test.py:
    
    from lib1 import Circle
    from lib2 import Triangle
    from lib3 import Rectangle
    
    # 统一计算面积函数的接口
    def getArea(shape):
        for name in ('area','getArea','get_area'):
            f = getattr(shape,name,None) # 这里如果shape不存在属性name,则返回None
            if f:  # 如果存在,则返回计算的结果
                return f()
    
    
    shape1 = Circle(2)
    shape2 = Triangle(3,4,5)
    shape3 = Rectangle(6,4)
    
    shapes = [shape1,shape2,shape3]
    print map(getArea,shapes)
    
    方法二:
    In [15]: from operator import methodcaller
    
    In [16]: methodcaller?
    Init signature: methodcaller(self, /, *args, **kwargs)
    Docstring:
    methodcaller(name, ...) --> methodcaller object
    
    Return a callable object that calls the given method on its operand.
    After f = methodcaller('name'), the call f(r) returns r.name().
    After g = methodcaller('name', 'date', foo=1), the call g(r) returns
    r.name('date', foo=1).
    File:           /usr/local/python3/lib/python3.7/operator.py
    Type:           type
    Subclasses:
    
    In [17]: s = 'abc123abc456'
    
    In [18]: s.find('abc',4)
    Out[18]: 6
    
    In [19]: methodcaller('find','abc',4)
    Out[19]: operator.methodcaller('find', 'abc', 4)
    
    In [20]: methodcaller('find','abc',4)(s)
    Out[20]: 6
    
    ====================================================================
    >>> s = 'abc123'
    >>> s.find('123'
    ... )
    3
    >>> # s 'find'
    >>> getattr(s,'find')
    <built-in method find of str object at 0x7f74c52fa110>
    >>> getattr(s,'find')('123')
    3
    >>> getattr(s,'pop')
    Traceback (most recent call last):
      File "<ipython-input-69-bdad44c9326c>", line 1, in <module>
        getattr(s,'pop')
    AttributeError: 'str' object has no attribute 'pop'
    
    >>> getattr(s,'pop',None)
    in __del__
    >>> from operator import methodcaller
    >>> s = 'abc123abc456'
    >>> s.find('abc',3)
    6
    >>> methodcaller('find','abc',3)
    operator.methodcaller('find', 'abc', 3)
    >>> methodcaller('find','abc',3)(s)
    6
    >>> 
    =========================================================================
    from lib1 import Circle
    from lib2 import Triangle
    from lib3 import Rectangle
    from operator import methodcaller
    
    def get_area(shape,method_name = ['area','get_area','getArea']):
        for name in method_name:
            if hasattr(shape,name):
                return methodcaller(name)(shape)
            # f = getattr(shape,name,None)
            # if f:
                # return f()
            
    shape1 = Circle(1)
    shape2 = Triangle(3,4,5)
    shape3 = Rectangle(4,6)
    
    shape_list = [shape1, shape2,shape3]
    # 获得面积列表
    area_list = list(map(get_area,shape_list))
    print(area_list)
    
    
  • 相关阅读:
    Laravel实用小功能
    _initialize() 区别 __construct()
    PHP websocket之聊天室实现
    原来PHP对象比数组用更少的内存
    PHP协程
    mongodb数据库的导出与导入
    我理解的数据结构(一)—— 数组(Array)
    Swoole 源码分析——Server模块之Worker事件循环
    PHP面试:说下什么是堆和堆排序?
    我理解的数据结构(二)—— 栈(Stack)
  • 原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13394569.html
Copyright © 2020-2023  润新知