python 描述器 详解_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.178linux.com/99690

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值