Python之屬性、特性和修飾符

做爲面對對象的核心內容,將從如下一個方面進行總結:
  1. property和@property
  2. __getattribute__()、__getattr__()、__setattr__()、__delattr__()
  3. 描述符__get__()、__set__()、__delete__()
  4. 不可變對象的實現

1. property和@property

  仍是直接上代碼來的方便node

  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用法spa

#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__()

  屬性查找過程:code

  __getattribute__  >>>> __dict__  >>>> __slots__ >>>> __getattr__orm

  主要注意__getattr__的用法和無限遞歸錯誤對象

  __getattr__在實例以及對應的__dict__中查找屬性失敗,那麼會調用__getattr__函數blog

  防止無限遞歸錯誤能夠使用如下兩種方法:遞歸

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

  例:get

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__的合集。

相關文章
相關標籤/搜索