Python 动态添加类方法

习题:

1. Shape基类,要求所有子类都必须提供面积的计算,子类有三角形、矩形、圆。

2. 上题圆类的数据可序列化

第一种方法:使用Mixin多继承组合的方式,混入其它类的属性和方法

第二种方法:使用装饰器装饰类,动态添加属性和方法

实例:

import math
import json
import msgpack
import pickle


class Shape:
    """防止直接调用父类的area方法"""
    @property
    def area(self):
        raise NotImplementedError('基类未实现')


class Triangle(Shape):
    """三角形"""
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c

    @property
    def area(self):
        p = (self.a+self.b+self.c)/2
        return math.sqrt(p*(p-self.a)*(p-self.b)*(p-self.c))


class Rectangle(Shape):
    """矩形"""
    def __init__(self,width,height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

def SerializableCircle(cls):
    """ 1.装饰器为类动态添加dumps方法"""
    # print(cls)
    def dumps(self,t='json'):
        if t == 'json':
            return json.dumps(self.__dict__)
        elif t == 'msgpack':
            return msgpack.packb(self.__dict__)
        elif t == 'pickle':
            with open('dump.txt','wb') as f:
                return pickle.dump(self.__dict__,f)
        else:
            raise NotImplementedError('没有实现的序列化')

    cls.dumps = dumps
    return cls


@SerializableCircle     # Circle=SerializableCircle(Circle)
class Circle(Shape):
    """圆形"""
    def __init__(self,radius):
        self.radius = radius

    @property
    def area(self):
        return (self.radius ** 2) * math.pi

    # def dumps(self,t='json'):
    #     if t == 'json':
    #         return json.dumps(self.__dict__)
    #     elif t == 'msgpack':
    #         return msgpack.packb(self.__dict__)
    #     elif t == 'pickle':
    #         with open('dump.txt','wb') as f:
    #             return pickle.dump(self.__dict__,f)
    #     else:
    #         raise NotImplementedError('没有实现的序列化')

# sc = Circle(4)
# sc.dumps('pickle')

class SerializableMixin:
    """序列化"""
    def dumps(self,t='json'):
        if t == 'json':
            return json.dumps(self.__dict__)
        elif t == 'msgpack':
            return msgpack.packb(self.__dict__)
        elif t == 'pickle':
            with open('dump.txt','wb') as f:
                return pickle.dump(self.__dict__,f)
        else:
            raise NotImplementedError('没有实现的序列化')

    def loads(self,t='json'):
        pass


class SerializableCircleMixin(SerializableMixin,Circle):
    """ 2.Mixin组合为类动态添加dumps方法"""
    pass


shapes = [Triangle(3,4,5), Rectangle(3,4), Circle(4)]
for s in shapes:
    print('The area of {} = {}'.format(s.__class__.__name__,s.area))

#Mixin
scm = SerializableCircleMixin(4)
print(scm.area)
s = scm.dumps('msgpack')
print(s)

#装饰器
sc = Circle(4)
s = sc.dumps('json')
print(s)

  

原文地址:https://www.cnblogs.com/i-honey/p/7831866.html