zoukankan      html  css  js  c++  java
  • pythoncookbook3 第8章 类与对象

    创建缓存实例--单例模式

    # import logging
    # a = logging.getLogger('foo')
    # c = logging.getLogger('foo')
    # b = logging.getLogger('bar')
    # print(a is c)

    # class Spam:
    # def __init__(self,name):
    # self.name = name

    import weakref

    # _cache = weakref.WeakValueDictionary()
    #
    # def get_spam(name):
    # if name not in _cache:
    # s = Spam(name)
    # _cache[name] = s
    # else:
    # s = _cache[name]
    # return s
    #
    #
    # a = get_spam('foo')
    # b = get_spam('bar')
    # c = get_spam('foo')
    # print(a is c)


    # class Spam:
    # def __init__(self):
    # print('__init__')
    # raise TypeError('不能实例化对象')
    #
    # @classmethod
    # def _new(cls,name):
    # print('__new__')
    # self = cls.__new__(cls)
    # self.name = name
    # return self
    #
    #
    # class CacheSpamManage:
    # def __init__(self):
    # self._cache = weakref.WeakValueDictionary()
    #
    # def get_spam(self, name):
    # if name not in self._cache:
    # s = Spam._new(name)
    # self._cache[name] = s
    # else:
    # s = self._cache[name]
    # return s
    #
    # def clear(self):
    # self._cache.clear()
    #
    #
    # s = CacheSpamManage()
    # a = s.get_spam('foo')
    # b = s.get_spam('bar')
    # c = s.get_spam('foo')
    # print(a is c)

    创建可管理的属性

    class Person:
    def __init__(self,first_name):
    self.first_name = first_name

    @property
    def first_name(self):
    return self._first_name

    @first_name.setter
    def first_name(self,value):
    if not isinstance(value,str):
    raise TypeError('参数必须是字符串')
    else:
    self._first_name = value

    p = Person('42')
    # p = Person(42)
    print(p.__dict__)

    #对象实例化的时候会触发 @first_name.setter包装的函数进行自动的类型检测
    #如果类中有多个属性需要进行类型检测使用描述符进行检测
    #如果类中需要进行类型检测的属性很少可以使用property进行类型检测

    # class Person:
    # def __init__(self,first_name):
    # self.set_first_name(first_name)
    #
    # def get_first_name(self):
    # return self._first_name
    #
    # def set_first_name(self,value):
    # if not isinstance(value,str):
    # raise TypeError('参数必须是字符串')
    # else:
    # self._first_name = value
    #
    # def del_first_name(self):
    # raise AttributeError('不能删除属性')
    #
    # name = property(get_first_name,set_first_name,del_first_name)
    #
    # s = Person('42')


    创建新的类或实例属性

    # class Typed:
    #
    # def __init__(self, name, expected_type):
    # self.name = name
    # self.expected_type = expected_type
    #
    # def __get__(self, instance, owner):
    # if instance is None:
    # return self
    # return instance.__dict__[self.name]
    #
    # def __set__(self, instance, value):
    # if not isinstance(value, self.expected_type):
    # raise TypeError('{}参数必须是{}类型'.format(value, self.expected_type.__name__))
    # instance.__dict__[self.name] = value
    #
    # def __delete__(self, instance):
    # del instance.__dict__[self.name]
    #
    #
    # def decorate_person(**kwargs):
    # def wapper(cls):
    # for name, expected_type in kwargs.items():
    # setattr(cls, name, Typed(name, expected_type))
    # return cls
    #
    # return wapper
    #
    #
    # @decorate_person(name=str, age=int, gender=str)
    # class Person:
    #
    # def __init__(self, name, age, gender):
    # self.name = name
    # self.age = age
    # self.gender = gender
    #
    #
    # p = Person(123, 18, '男')
    # print(p.name)
    # print(p.age)
    # print(p.gender)

    """
    如果你只是想简单的自定义某个类的单个属性访问的话就
    不用去写描述器了。这种情况下使用 property 技术会更加容易。
    """


    class Person:
    def __init__(self,name):
    self.name = name

    @property
    def name(self):
    return self._name

    @name.setter
    def name(self, value):
    if not isinstance(value, str):
    raise TypeError('{}参数必须是{}类型'.format(value,str.__name__))
    self._name = value

    # p = Person(123)
    #TypeError: 123参数必须是str类型
    p = Person('123')


    使用延迟计算属性
    import math

    class lazyproperty:

    def __init__(self,func):
    self.func = func

    def __get__(self, instance, owner):
    if instance is None:
    return self
    else:
    value = self.func(instance)
    setattr(instance,self.func.__name__,value)
    return value


    #另一个实现方式没有上一种方法高效但是可以阻止给属性赋值


    def lazyproperty(func):
    name = '_lazy_' + func.__name__
    @property
    def lazy(args):

    if hasattr(args, name):
    return getattr(args, name)
    else:
    value = func(args)
    setattr(args, name, value)
    return value
    return lazy


    class Circle:
    def __init__(self,radius):
    self.radius = radius

    @lazyproperty
    def area(self):
    print('Computing area')
    return math.pi * self.radius ** 2

    @lazyproperty
    def perimeter(self):
    print('Computing perimeter')
    return math.pi * 2 * self.radius

    c = Circle(4.0)
    """
    c.radius
    4.0

    c.area
    Computing area
    50.26548245743669

    c.area
    50.26548245743669

    vars(c)
    {'radius': 4.0, 'area': 50.26548245743669}

    c.perimeter
    Computing perimeter
    25.132741228718345

    vars(c)
    {'radius': 4.0, 'area': 50.26548245743669, 'perimeter': 25.132741228718345}

    c.perimeter
    25.132741228718345
    """


    简化数据结构的初始化

    import math


    class Structure:
    _fields = []

    def __init__(self, *args, **kwargs):
    if len(args) != len(self._fields):
    raise TypeError(('Expected {} arguments'.format(len(self._fields))))

    for name, value in zip(self._fields, args):
    setattr(self, name, value)

    expected_field = kwargs.keys() - self._fields

    for name in expected_field:
    setattr(self, name, kwargs.pop(name))

    if kwargs:
    raise TypeError('Duplicate values for {}'.format(','.join(kwargs)))


    class Stock(Structure):
    _fields = ['name','age','gender']

    s = Stock('小于',18,'男',date='2017-1-21')

    print(vars(s))
    #{'name': '小于', 'age': 18, 'gender': '男', 'date': '2017-1-21'}

    #如果有很多需要初始化的数据量比较小的类使用这个方法会很方便

    定义接口或者抽象基类
    
    
    from abc import ABCMeta, abstractmethod

    class IStream(metaclass=ABCMeta):

    @abstractmethod
    def read(self, maxbytes = -1):
    pass

    @abstractmethod
    def write(self, data):
    pass


    class S(IStream):
    def __init__(self,a):
    self.a = a

    def read(self, maxbytes = -1):
    pass
    def write(self, data):
    pass

    s = S('a')
    #TypeError: Can't instantiate abstract class S with abstract methods read, write
    #继承抽象基类定义的类必须实现抽象类中的abstractmethod装饰的方法

    @abstractmethod 还能注解静态方法、类方法和 properties 。你只需保证这个注
    解紧靠在函数定义前即可:

    class A(metaclass=ABCMeta):
      @property
      @abstractmethod
      def name(self):
        pass


      @name.setter
      @abstractmethod
      def name(self, value):
        pass


    实现数据模型的类型约束

    class Descriptor:

    def __init__(self, name=None, **opts):
    self.name = name
    for key, value in opts.items():
    setattr(self, key, value)

    def __set__(self, instance, value):
    instance.__dict__[self.name] = value


    # class Type(Descriptor):
    # expected_type = type(None)
    #
    # def __set__(self, instance, value):
    # if not isinstance(value, self.expected_type):
    # raise TypeError('expected' + str(self.expected_type))
    # super().__set__(instance, value)


    # 实现Type装饰器
    def Type(expected_type, cls=None):

    if cls is None:
    return lambda cls: Type(expected_type, cls)

    super_set = cls.__set__

    def __set__(self, instance, value):
    if not isinstance(value, expected_type):
    raise TypeError('expected' + str(expected_type))
    super_set(self, instance, value)

    cls.__set__ = __set__
    return cls


    # class Unsigned(Descriptor):
    #
    # def __set__(self, instance, value):
    # if value < 0:
    # raise ValueError('expected >= 0')
    # super().__set__(instance, value)

    # Unsigned装饰器

    def Unsigned(cls):
    super_set = cls.__set__

    def __set__(self, instance, value):
    if value < 0:
    raise ValueError('expected >= 0')
    super_set(self, instance, value)

    cls.__set__ = __set__
    return cls


    #
    # class MaxSizes(Descriptor):
    #
    # def __init__(self, name=None, **opts):
    # if 'size' not in opts:
    # raise TypeError('missing in opt')
    # super().__init__(name, **opts)
    #
    # def __set__(self, instance, value):
    # if len(value) >= self.size:
    # raise ValueError('size must be <' + str(self.size))
    # super().__set__(instance, value)

    # MaxSizes装饰器
    def MaxSizes(cls):

    super_init = cls.__init__

    def __init__(self, name=None, **kwargs):
    if 'size' not in kwargs:
    raise TypeError('missing in opt')
    super_init(self, name, **kwargs)

    cls.__init__ = __init__

    super_set = cls.__set__

    def __set__(self, instance, value):
    if len(value) >= self.size:
    raise ValueError('size must be <' + str(self.size))
    super_set(self, instance, value)

    cls.__set__ = __set__
    return cls


    @Type(int)
    class Integer(Descriptor):
    pass


    @Unsigned
    class UnsignedInteger(Integer):
    pass


    @Type(float)
    class Float(Descriptor):
    pass


    @Unsigned
    class UnsignedFloat(Float):
    pass


    @Type(str)
    class Str(Descriptor):
    pass


    @MaxSizes
    class MaxSizesStr(Str):
    pass


    # 使用装饰器进行类型检测
    # def check_attr(**kwargs):
    # def decorate(cls):
    # for key, value in kwargs.items():
    # if isinstance(value, Descriptor):
    # value.name = key
    # setattr(cls, key, value)
    # else:
    # setattr(cls, key, value(key))
    # return cls
    #
    # return decorate


    # 使用元类进行类型检测
    # class MetaType(type):
    #
    # def __new__(cls, cls_name, base, method):
    # for key, value in method.items():
    # if isinstance(value, Descriptor):
    # value.name = key
    #
    # return type.__new__(cls, cls_name, base, method)


    # @check_attr(name=MaxSizesStr(size=8),shares=UnsignedInteger,price=UnsignedFloat)
    class Share():
    name = MaxSizesStr('name',size=8)
    shares = UnsignedInteger('shares')
    price = UnsignedFloat('price')

    def __init__(self, name, shares, price):
    self.name = name
    self.shares = shares
    self.price = price


    s = Share('阿里', 70, 70.0)
    print(vars(s))
    """
    这种方式定义的类跟之前的效果一样,而且执行速度会更快。设置一个简单的类型
    属性的值,装饰器方式要比之前的混入类的方式几乎快 100%。
    """
    
    
  • 相关阅读:
    维特比(Viterbi)算法解最优状态序列
    c#重要知识点复习1---程序流程控制
    学C# Hook原理及EasyHook简易教程
    EmguCV 绘画图形
    EmguCV创建/保存图片
    EmguCV中图像类型进行转换
    basler 相机拍照简单类综合Emgu.CV---得到图档--原创
    RotatedRect 类的用法
    EmguCv“线段” 结构类型学习
    aforge 学习-基本图像处理要用的类库
  • 原文地址:https://www.cnblogs.com/louzi/p/10395469.html
Copyright © 2011-2022 走看看