您的位置:首页 > 编程语言 > Python开发

python __getattr__ 和 __setattr__方法、属性私有化

2018-02-07 14:53 609 查看


Python setattr() 函数

描述
语法

setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。

setattr 语法:
setattr(object, name, value)


参数

object -- 对象。

name -- 字符串,对象属性。

value -- 属性值。
返回值
实例

无。

以下实例展示了 setattr 的使用方法:

class A(object):

 bar = 1

a = A()

getattr(a, 'bar')          # 获取属性 bar 值

setattr(a, 'bar', 5)       # 设置属性 bar 值

a.bar

Out[2]: 5


__getattr__方法


拦截点号运算。当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法

[python] view
plain copy

class empty:  

    def__getattr__(self, attrname):  

        ifattrname =="age":  

            return40  

        else:  

            raiseAttributeError, attrname  

   

x =empty()  

print(x.age)       #40  

print(x.name)      #error text omitted.....AttributeError, name  

这里empty类和实例x并没有属性age,所以执行x.age时,就会调用__getattr__方法,对于name也是同样。


__setattr__方法

会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value).这个需要注意。当在__setattr__方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name']
= value.


实现属性的私有化

[python] view
plain copy

class PrivateExc(Exception):  

    pass  

   

class Privacy:  

    def__setattr__(self, attrname, value):  

        ifattrname inself.privates:  

            raisePrivateExc(attrname, self)  

        else:  

            self.__dict__[attrname]= value  

   

classTest1(Privacy):  

    privates= ["age"]  

   

classTest2(Privacy):  

    privates= ["name","age"]  

    def__init__(self):  

        self.__dict__["name"]= "sun"  

   

x =Test1()  

y =Test2()  

x.name = "Tom"         #执行成功  

x.age =20              #执行失败,产生异常,该属性在privates列表内  

y.name = "Mike"        #执行失败,产生异常,该属性在privates列表内  

y.age =20              #执行成功  

上述方式是python实现属性私有化的首选方式。

Python Class 对象或类型通过内置成员 __dict__ 来存储成员信息。

  我们还可以通过重载 __getattr__ 和 __setattr__ 来拦截对成员的访问,需要注意的是 __getattr__ 只有在访问不存在的成员时才会被调用。

>>> class Class1:

  def __getattr__(self, name):

    print "__getattr__"

    return None

  def __setattr__(self, name, value):

    print "__setattr__"

    self.__dict__[name] = value

    

>>> a = Class1()

>>> a.x

__getattr__

>>> a.x = 123

__setattr__

>>> a.x

123


  如果类型继承自 object,我们可以使用 __getattribute__ 来拦截所有(包括不存在的成员)的获取操作。

  注意在 __getattribute__ 中不要使用 "return self.__dict__[name]" 来返回结果,因为在访问 "self.__dict__" 时同样会被 __getattribute__ 拦截,从而造成无限递归形成死循环。

>>> class Class1(object):

  def __getattribute__(self, name):

    print "__getattribute__"

    return object.__getattribute__(self, name)

  

>>> a = Class1()

>>> a.x

__getattribute__

Traceback (most recent call last):

 File "<pyshell#3>", line 1, in <module>

 a.x

 File "<pyshell#1>", line 4, in __getattribute__

 return object.__getattribute__(self, name)

AttributeError: 'Class1' object has no attribute 'x'

>>> a.x = 123

>>> a.x

__getattribute__

123
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: