• Python之属性、特性和修饰符


    作为面对对象的核心内容,将从以下一个方面进行总结:
      1. property和@property
      2. __getattribute__()、__getattr__()、__setattr__()、__delattr__()
      3. 描述符__get__()、__set__()、__delete__()
      4. 不可变对象的实现

    1. property和@property

      还是直接上代码来的方便

      property()用法

    #coding = utf-8
    
    class property_test:
        def __init__(self, size=10):
            self.size=size
            
        def __getsize__(self):
            return self.size
    
        def __setsize__(self, value):
            self.size = value
    
        def __deletesize__(self):
      
            del self.size
    
        x= property(__getsize__, __setsize__, __deletesize__)    
    
    if __name__ == "__main__":
        p = property_test()
        p.x = 20
        print (p.size)  >>> 20

       @property用法

    #coding = utf-8
    
    '''class property_test:
        def __init__(self, size=10):
            self.size=size
            
        def __getsize__(self):
            return self.size
    
        def __setsize__(self, value):
            self.size = value
    
        def __deletesize__(self):
      
            del self.size
    
        x= property(__getsize__, __setsize__, __deletesize__)   '''
    
    class property_test:
        def __init__(self, size=10):
            self.sizevalue=size     #特别注意sizevalue不要和size同名
    
        @property
        def size(self):
            return self.sizevalue
    
        @size.setter
        def size(self, value):
            self.sizevalue = value
    
        @size.deleter
        def size(self):
            del self.sizevalue
    
    if __name__ == "__main__":
        p = property_test()  
        p.size = 20
        p.size += 20
        print (p.size, p.sizevalue)

    2. __getattribute__()、__getattr__()、__setattr__()、__delattr__()

      属性查找过程:

      __getattribute__  >>>> __dict__  >>>> __slots__ >>>> __getattr__

      主要注意__getattr__的用法和无限递归错误

      __getattr__在实例以及对应的__dict__中查找属性失败,那么会调用__getattr__函数

      防止无限递归错误可以使用以下两种方法:

       1. self.__dict__[name] = value
            2. super().__setattr__(name,value)

      例:

    class rectange:
        def __init__(self, width=20, height=40):
            self.width = width
            self.height = height
    
        def __getattr__(self, name):
            return self.width
            
        def __setattr__(self,name, value):
            if name == "squ":
                super().__setattr__(name,value)
                super().__setattr__("width",40)
                super().__setattr__("height",40)
                print (name, self.__dict__[name])
            else:
                #self.__dict__[name] = value
                super().__setattr__(name,value)
                print (name, self.__dict__[name])
        
    if __name__ == "__main__":
        p = rectange()
        p.width = 10
        p.squ = 80
        print (p.width, p.height)

    3. 描述符

      描述符说的直白点就是一个“绑定行为”的对象属性,通过__get__()、__set__()和__delete__()函数重写描述符属性

      如果上述方法被定义在一个对象中,那么这个对象就是一个描述符

      当定义拥有者类时,每个修饰符对象都是修饰符类的实例,绑定在类级别的属性上

      方法的原型为:

      ① __get__(self, instance, owner)

      ② __set__(self, instance, value)

      ③ __del__(self, instance)

    class A:
        def __init(self):
            self.color = "red"
            
        def __get__(self, instance, owner):
            print ("get instance:", instance)
            print ("get owner:", owner)
            return self.color
    
        def __set__(self, instance, value):
       
            print ("set instance:", instance)
            print ("set value:", value)
            self.color = value
    
        def __delete__(self, instance):
    
            print ("delete instance:", instance)
            del self.color
    
    class B:
        a = A()
        def __init__(self):
            self.color = "black"
        
    if __name__ == "__main__":
        b = B()
        b.a = "blue"
        b.color = b.a
        del b.a

    4. 使用__slots__实现不可变对象

      首先说明下__slots__方法,具体可以查看https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868200605560b1bd3c660bf494282ede59fee17e781000

      方法:

      1. 把__slots__设为唯一允许操作的属性,这会使得对象内部的__dict__不再有效并阻止对其他属性的访问

      2. 在__init__中调用基类的__setattr__实现

      3. 在__setattr__中抛出异常

      例:

    #coding=utf-8
    
    class student:
        __slots__ = ("name")
    
        def __init__(self, name):
            super().__setattr__("name", name)
            self.name = name
            print (self.name)
    
        def __str__(self):
            return "{0.name}".format(self)
    
        def __setattr__(self, name, value):
            raise Exception(" '{__class__.__name__}' has no
            attribute '{name}'".format(__class__=self.__class__,name=self.name))
    
    if __name__ == "__main__":
        s = student("zhanglin")
        #s.name = "lizhi"
    __slot__定义类中可以被外界访问的属性,类似node中的exports。

    当父类中定义了__slot__时,不能向父类中添加属性。如果子类中没有定义__slot__,则子类不受父类__slot__定义的限制。

    如果父类与子类中都定义了__slot__,则影响的结果为父类与子类__slot__的合集。

  • 相关阅读:
    程序员最怕的事
    钱钟书是怎样做读书笔记的 杨绛
    编码风格不是编码规范
    Google Reader明日关闭:14款替代品对比
    移动应用设计领域中最拔尖的15大应用
    TOGAF:企业信息化复杂吗?
    敏捷个人回顾以及体系2014版线下分享活动
    敏捷个人手机应用iOS和Android公开注册
    IT人的自我导向型学习:学习的4个层次
    IT人的自我导向型学习:学习的3个维度
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/8556001.html
Copyright © 2020-2023  润新知