需求:
某项目中,我们的代码使用了三个不同库中的图形类,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)