python装饰器实现私有属性,公有属性

通过带参的函数装饰器返回一个包装类/委托类(主要实现了__getattr__ , __setattr__来拦截属性),

使用装饰器及委托类的好处是不用每个类都去实现__setattr__, __getattribute__ ,对你没看错是__getattribute__.

在委托类中只需实现__getattr__ 即可. 

简单区别:

__getattribute__ : 实例对象通过 .(点) 操作符都会触发

 __getattr__        :获取未定义的属性会触发

管理属性区别

委托类的模式有点像shell ,  被装饰的类有点像内核. 内核中随意弄, 而操作shell却有限制.

装饰器的好处就在于完全和主体分离.



#通过装饰器实现私有属性
#整体基于一个委托类
#主要通过__getattr__ , __setattr__ 来拦截属性的访问以及设置

def print_trace(*args):                     #输出语句
    print('['+' '.join(map(str,args)) +']')
#带参数的函数装饰器,返回一个包装类
def Private(*privates):                             #privates 接受一系列的私有属性
    def decorator(aClass):                          #函数装饰器,接受一个类对象
        class private_class:                        #返回的包装类
            errstr_getattr = '获取私有属性失败'
            errstr_setattr = '设置私有属性失败'
            def __init__(self,*args,**kwargs):
                self.wrapper = aClass(*args,**kwargs)   #实例属性wrapper 创建一个被装饰类的对象

            def __getattr__(self, attr):                #用于wrapper对象的属性获取
                print_trace('__getattr__:',attr)
                if attr in privates:                    #通过闭包引用的额外作用域,获取privates元组,如果attr是私有属性则抛异常
                    raise TypeError(private_class.errstr_getattr+':'+str(attr))
                return getattr(self.wrapper,attr)       #不是一开始设置的私有属性,则通过getattr获取

            def __setattr__(self, attr, value):         #用于wrapper对象的属性设置
                print_trace('__setattr__:',attr,value)
                if 'wrapper' == attr:                       #'wrapper'属性是委托类自己的属性,放行
                    object.__setattr__(self,attr,value)      #或者使用self.__dict__[attr] = value , 两者皆可
                elif attr in privates:                      #如果attr是私有属性则出错
                    raise TypeError(private_class.errstr_setattr+':'+str(attr))
                else:
                    object.__setattr__(self.wrapper,attr,value) #委托类自身只有一个wrapper属性,其他属性通过wrapper对象获取
        return private_class
    return decorator

@Private("data",'size')                 #把data,size作为私有属性
class TestClass:
    def __init__(self,label,start):
        self.label = label
        self.data = start
    def size(self):
        return len(self.data)
    def double(self):
        for i in range(self.size()):
            self.data[i] = self.data[i] * 2
    def display(self):
        print("%s => %s"%(self.label,self.data))

t = TestClass()
#t.data   , t.size 将出错 


#通用的Private, Public 装饰器
#打印函数
def trace(*args):
    print('[' +' '.join(map(str,args))+']')

#通用的函数装饰器
#4层结构
#同样的通过委托类来实现
def access_func(test_func):                 #接受一个函数对象,用于判断是否是私有,公有属性
    def decorator(aClass):                  #装饰器
        class WrappedClass:                 #返回的内部类
            err_getattr = "获取私有属性失败"
            err_setattr = "设置私有属性失败"
            def __init__(self,*args, **kwargs):
                self.wrapped = aClass(*args,**kwargs)     #被装饰的对象

            def __getattr__(self, attr):                  #__getattr__ 拦截未知属性
                if test_func(attr):                       #私有公有属性主要通过 闭包中的test_func 来判断
                    raise TypeError(WrappedClass.err_getattr,attr)
                return getattr(self.wrapped,attr)

            def __setattr__(self, attr, value):
                if 'wrapped' == attr:                     #WrappedClass自身属性通过
                    object.__setattr__(self,attr,value)
                elif test_func(attr):
                    raise TypeError(WrappedClass.err_setattr,attr)
                else:
                    object.__setattr__(self.wrapped,attr,value)
        return WrappedClass
    return decorator

#最上层的函数包裹,通过调用access_func 来返回装饰器
#通过传入匿名函数给下面函数使用,最内层的WrappedClass通过闭包来获取

def private_decorator(*private_attrs):              #传入私有属性,当外部访问私有属性抛异常
    return access_func(lambda attr: attr in private_attrs)

def public_decorator(*public_attrs):                #传入共有属性,当外部访问非公有属性时抛异常
    return access_func(lambda  attr : attr not in public_attrs)

@public_decorator('age')        #测试
class Person:
    def __init__(self,name='Person',age=10):
        self.name = name
        self.age = age

p = Person()
print(p.age)        #ok
print(p.name)       #error



最后提供一种很烂的方法来实现私有属性,公有属性


#私有,公有属性用 __getattribute__ 来实现
#只提供一种思路 

def access_control(test_func):
    def decorator(aClass):
        def getattr(self,attr):
            print('get:',attr)
            if test_func(attr):
                raise TypeError('私有属性获取失败 :' ,attr)
            return object.__getattribute__(self,attr)
        aClass.__getattribute__ = getattr                       #核心代码就这一句
        return aClass
    return decorator

def private_decorator(*args):
    return access_control(lambda attr : attr in args)
def public_decorator(*args):
    return access_control(lambda attr : attr not in args)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值