Python 的描述器Descriptors

Python 的描述器Descriptors

描述器的表現
—————————————————————————
用到3個魔術方法: __get__()\__set__()\__delete__()

方法簽名:
object.__get__(self, instance, owner)
object.__set__(self, instance, value)
object.__delete__(self, instance)

self 指當前實例,調用者
instance是owner的實例
owner是屬性的所屬的類

描述器定義
——————————————————————————
Python中,一個類實現了__get__()\__set__()\__delete__()中的任一種方法,就是描述器。

非數據描述符:僅實現__get__
數據描述符:實現__get__ \ __set__

如果一個類的類屬性設置為描述器,它被稱為owner屬主

屬性的訪問順序
——————————————————————————
class A:
def __init__(self):
self.a1 = ‘a1’
print(‘A init’)

def __get__(self, instance, owner):
print(“A.__get__{} {} {}”.format(self, instance, owner))
return self

def __set__(self, instance, value):
print(“A.__set__{} {} {}”.format(self , instance , value))
self.data = value

def __delete__(self, instance):
print(“A.__delete__{} {}”.format(self , instance))
del self

class B:
x = A()
def __init__(self):
print(‘B init’)
self.y = ‘y1’
self.x = ‘b.x’ #增加實例屬性

print(‘-‘*20)
print(B.x)
print(B.x.a1)

print(‘=’*20)
b = B()
print(b.x)
print(b.x.data)
print(b.__dict__)

b.x.a1 = 200

print(b.x.__dict__)
print(b.__dict__)

del b.x
print(b.x)
print(b.x.a1)
print(b.__dict__)

print(‘+’*20)

b.x = 300 #調用數據數據描述符的__set__方法,或非數據描述器的實例覆蓋
B.x = 600 #賦值即定義,覆蓋類屬性
print(b.x)
print(b.__dict__)
print(B.__dict__)

屬性查找順序:
實例的__dict__優先于非數據描述符
數據描述符優先于實例的__dict__ (屬性查找變成了描述器的__set__)

Python中的描述器應用
————————————————————————————
staticmethod() 和 classmethod()是非數據描述器。實例可以重新定義和覆蓋方法。

property()是數據描述符。實例不能覆蓋屬性的行為。

class staticmethod:
def __init__(self, fn):
self._fn = fn
print(‘1 init’)

def __get__(self, instance, owner):
print(“1.__get__{} {} {}”.format(self, instance, owner))
return self._fn

class classmethod:
def __init__(self , fn):
self._fn = fn
print(‘2 init’)

def __get__(self, instance , owner):
from functools import partial
print(“2.__get__{} {} {}”.format(self , instance , owner))
return partial(self._fn, owner)

class property:
def __init__(self, fn):
self._fn = fn
self.setfn = None
print(‘3 init’)

def __get__(self, instance, owner):
print(“3.__get__{} {} {}”.format(self , instance , owner))
return self._fn(instance)

def __set__(self, instance, value):
print(“3.__set__{} {} {}”.format(self , instance , value))
self.setfn(instance,value)

# def getter(self):
# return self.__get__

def setter(self,fn):
self.setfn = fn
return self

class B:
@staticmethod # add = staticmethod(add) -> add
def add(x, y):
return x + y

@classmethod # add = staticmethod(add) -> add
def add(cls, x, y):
return x + y

@property # x = property(x) -> x
def x(self):
return self._x

@x.setter # x = x.setter(x) -> x
def x(self, value):
self._x = value

def __init__(self):
self._x = 6

b = B()
# print(b.add(3, 5))
# print(b.__dict__)
# print(B.__dict__)

print(b.x)
b.x = 10
print(b.x)

本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/99690

(0)
JacoJaco
上一篇 2018-05-28 22:13
下一篇 2018-05-29 09:19

相關推薦

  • Python文件操作

    計算機體系架構 運算器:完成各種算術運算、邏輯運算、出具傳輸等數據加工處理 控制器:控制程序的執行 CPU = 運算器 + 控制器 存儲器:用于記憶程序的數據,內存 輸入設備:將數據或程序輸入到計算機中 輸出設備:將數據或程序的處理結果展示給用戶 文件IO常用操作 open 打開 read 讀取 write 寫入 close 關閉 readline 行讀取 …

    Python筆記 2018-05-02
  • Python的內置數據結構

    字符串、列表、元組

    Python筆記 2018-03-31
  • 面向對象,魔術方法

    面向對象 一面向對象 什么是面向對象: 一種認識世界、分析世界的方法論。將萬事萬物抽象為類。 類class: 類是抽象的概念,是萬事萬物的抽象,是一類事物的共同集合的集合。 用計算機語言來描述類,就是屬性和方法的集合。 對象instance,object: 對象是類的具象,是一個實體。 每個個體都是抽象類的不同實體。 哲學 一切皆對象 對象是數據和操作的封裝…

    Python筆記 2018-05-14
  • Python內建函數

    內建函數 標識id() 返回對象的唯一標識,CPython返回內存地址 哈希hash() 返回一個對象的hash值 類型type() 返回對象的類型 類型轉換 int()、float()、bin()、hex()、oct()、bool()、list()、tuple()、dict()、set()、complex()、bytes()、bytearray() 輸入i…

    2018-04-08
  • 函數

    函數 數學定義:y=f(x),y是x的函數,x是自變量 Python函數 有若干個語句塊,函數名稱,參數列表構成,它是組織代碼的最小單元 完成一定作用 函數的作用 結構化編程對代碼的最基本的封裝,一般按照功能組織一段代碼 封裝的目的為了復用,減少了冗余代碼 代碼更加簡潔美觀,更加易讀 函數的分類 內建函數,如max(),reversed()等 庫函數,如ma…

    2018-04-16
  • 第一周作業

    linux基礎

    Python筆記 2018-05-12
欧美性久久久久