浅析python中属性管理

(1)什么是python属性管理?为什么要管理?在python的OOP中,属性有类的属性及实例对象的属性,有调用,赋值,删除的基本操作,属性管理就是在属性的调用,赋值,删除操作进行管理,比如,在属性赋值时,可以先判定其是不是符合要求的值,或者在调用时有其他特殊的要求。
(2)怎么样进行属性管理?属性管理主要有2种方法,一种是基于property方法或者描述符协议(discriptor protocol),构造出一个特殊的类,然后实例化后作为待管理类的类属性,该方法只能针对特定的属性,第二种是基于__getattr__或者__getattribute__的属性截取方法,在属性调用时候,截取进行操作完成既定目的。
(3)描述符协议与property方法描述符协议实际是一种定义了__set__,get,__delete__方法的类A,当该类对象被赋予为某类B的类属性后,调用类B或类B实例对象的属性,将调用类A的__get__方法,对类B或类B实例对象的属性进行赋值将调用类A的__set__方法,删除将调用类A的__delete__方法。如 下:

class Dscrip:
    def __set__(self,instance,value):
        print('set...')
        instance._name=value
    def __get__(self,instance,owner):
        print('get...')
        return instance._name
    def __delete__(self, instance):
        print('bye...')
        del instance._name

class test1:
    def __init__(self,name):
        self._name=name
    name=Dscrip()

print('test1'.center(50,'*'))
a=test1('tom')
print(a.name)
a.name='John'
print(a.name)
try:
    print(test1.name)
except AttributeError as e:
    print('Error',e)
del a.name
try:
    print(a.name)
except:
    print('Nothing...')

输出:

**********************test1***********************
get...
tom
set...
get...
John
get...
Error 'NoneType' object has no attribute '_name'
bye...
get...
Nothing...

需要说明的是描述符协议__set__(self,instance,value)中self是描述符实例对象,instance是虚拟属性所在的实例对象,value是待赋值的值,get(self,instance,owner)中,owner是instance的类,其他的同上。
property方法:

class test2:
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        print('get...')
        return self._name
    @name.setter
    def name(self,value):
        print('set..')
        self._name=value
    @name.deleter
    def name(self):
        print('delete...')
        del self._name

输出:

**********************test2***********************
get...
tom
set..
get...
John
<property object at 0x0000015E8CDC4278>
delete...
get...
Nothing...

实际上,property是一种特殊的描述符协议,下面是等效的property方法:

class Property:
    def __init__(self,fget=None,fset=None,fdel=None):
        self.fget=fget
        self.fset=fset
        self.fdel=fdel
    def __get__(self,instance,owner):
        if instance is None:
            return self
        if self.fget is None:
            raise AttributeError('cant get attribute')
        print('property get...')
        return self.fget(instance)
    def __set__(self,instance,value):
        if instance is None:
            return self
        if self.fset is None:
            raise AttributeError('cannt set attribute')
        print('property set...')
        self.fset(instance,value)
    def __delete__(self,instance):
        if instance is None:
        	return self
        print('property delete...')
        self.fdel(instance)

class test3:
    def __init__(self,name):
        self._name=name
    def set_name(self,value):
        self._name=value
    def get_name(self):
        return self._name
    def del_name(self):
        print('delete...')
        del self._name
    name=Property(get_name,set_name,del_name)

print('test3'.center(50,'*'))
a=test3('tom')
print(a.name)
a.name='John'
print(a.name)
try:
    print(test3.name)
except AttributeError as e:
    print('Error',e)
del a.name
try:
    print(a.name)
except:
    print('Nothing...')

输出:

**********************test3***********************
property get...
tom
property set...
property get...
John
property get...
Error 'NoneType' object has no attribute '_name'
property delete...
delete...
property get...
Nothing...

(4)通过__getattr__或__getattribute__操作符重载方法,该方法实际是将未知的或者所有的属性的获取进行截取,然后添加相应的操作,本质上也是虚拟属性。
简而言之,__getattr__只对未知的属性的获取进行截取,__getattributes__对所有属性获取进行截取,setattr,delattr__对所有属性的赋值,删除进行截取。
这种方法,如果__getattribute__或者__setattr
,__delattr__中有对类实例对象(self)的调用,赋值,就很容易造成无限循环,因为调用,或者赋值将调用自身,防止的方法有两个:(a)用self.dict[attr]=value代替self.attr=value(b)使用object.getattribute(self,attr),object.setattribute(self,attr,value)进行更高一级的调用,赋值。
对于内建操作符的截取情况,如下图:
在这里插入图片描述在这里插入图片描述

class GetAttr:
    eggs=88
    def __init__(self):
        self.spam=77
    def __len__(self):
        print('__len__:42')
        return 42
    def __getattr__(self, item):
        print('getattr:'+item)
        if item=='__str__':
            return lambda *args:'[Getattr str]'
        else:
            return lambda *args:None

class GetAttribute:
    eggs=88
    def __init__(self):
        self.spam=77
    def __len__(self):
        print('__len__:42')
        return 42
    def __getattribute__(self, item):
        print('getattribute:'+item)
        if item=='__str__':
            return lambda *args:'[Getattribute str]'
        else:
            return lambda *args:None

for cls in GetAttr,GetAttribute:
    print('\n'+cls.__name__.ljust(50,'*'))

    x=cls()
    x.eggs
    x.spam
    x.other
    len(x)
    try:x[0]
    except:print('fail[]')
    try:x+99
    except:print('fail+')
    try:x()
    except:print('fail()')
    try:x.__len__()
    except:print('fail __len__')
    try:x.__call__()
    except:print('fail __call__')
    print(x.__str__())
    print(x)

输出:

GetAttr*******************************************
getattr:other
__len__:42
fail[]
fail+
fail()
__len__:42
getattr:__call__
<__main__.GetAttr object at 0x0000021F65BF7AC8>
<__main__.GetAttr object at 0x0000021F65BF7AC8>
GetAttribute**************************************
getattribute:eggs
getattribute:spam
getattribute:other
__len__:42
fail[]
fail+
fail()
getattribute:__len__
getattribute:__call__
getattribute:__str__
[Getattribute str]
<__main__.GetAttribute object at 0x0000021F65DDE5F8>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值