先介绍几个类中的应用__getattr__,__setattr__,__get__,__set__,__getattribute__,。
__getattr__:当在类中找不到attribute的时候,会调用__getattr__,并执行其中的自定义代码。所有在类中定义的属性都包含在__dict__中,也就是说如果在__dict__中找不到对应的属性名,则__getattr__被触发。
class get_try(object):
    def __init__(self,value):
        self.value=value
    def __getattr__(self, item): #当找不到类中的属性的时候,将会被调用
        self.value=item if __name__ == "__main__":
    g=get_try('value')
    g.value1   #调用了g.value1,value1传入__getattr__的item.调用__getattr后,value=value1
    print g.value
print g.__dict_
 
E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter7.py
value1
{'value': 'value1'}
结果打印的时候g.value的值是value1
 
__getattribute__:无条件被调用,如果同时定义了__getattr__, 则__getattr__不会被调用。
class get_try(object):
    def __init__(self,value):
        self.value=value
    def __getattr__(self, item):
        self.value=item
    def __getattribute__(self, item):
        print item if __name__ == "__main__":
    g=get_try('value')
    g.value1
E:\python2.7.11\python.exe E:/py_prj/fluent_python/chapter7.py
value1
结果和之前一样。
 
__setattr__当需要自己对属性进行定义的时候,会被调用。比如self.att=value就会变成self.__setattr__(“att”,value)class get_try():    def __init__(self,value):
        self.value=value
    def __getattr__(self, item):
        self.value=item
    def __getattribute__(self, item):
        print item
    def __setattr__(self, key, value):
        self.__dict__[key]=value if __name__ == "__main__":
    g=get_try('value')
    g.value1=3
    print g.value1
    print g.__dict__
E:\python2.7.11\python.exe E:/py_prj/python_cookbook/chapter8.py
3
{'value1': 3, 'value': 'value'}
需要注意的是在__setattr__的时候不能进行self.key=value的赋值,因为这个方式会使得不停调用self.__setattr__。这样会形成无穷的递归循环。最终导致堆栈溢出异常。当我们调用的时候,报的错误就像下面这种
  File "E:/py_prj/python_cookbook/chapter8.py", line 107, in __setattr__
    self.key=value
  File "E:/py_prj/python_cookbook/chapter8.py", line 107, in __setattr__
    self.key=value
RuntimeError: maximum recursion depth exceeded
其实我们不实现__setattr__的时候,在给属性赋值的时候也会隐含的调用这个函数。那么这样实现的好处是什么呢?好处是我们可以指定给哪些属性进行赋值。
class get_try():
    def __init__(self,value):
        self.value=value
    def __getattr__(self, item):
        self.value=item
    def __getattribute__(self, item):
        print item
    def __setattr__(self, key, value):
        if key == 'value1':
            print 'incorrect key'
        else
:
            self.__dict__[key]=value if __name__ == "__main__":
    g=get_try('value')
    g.value1=3
    g.value2=4
    print g.__dict__
E:\python2.7.11\python.exe E:/py_prj/python_cookbook/chapter8.py
incorrect key
{'value2': 4, 'value': 'value'}
上面的代码中,当对value1进行赋值的时候,首先进行判断。如果是value1则打印incorrect key。所以看到当对value2进行赋值的时候是成功的。同样的道理,我们可以用__setattr__在防止后续对类中已有的属性进行赋值:
class get_try():
    def __init__(self,value):
        self.value=value
    def __getattr__(self, item):
        self.value=item
    def __getattribute__(self, item):
        print item
    def __setattr__(self, key, value):
        if key in self.__dict__:
            print 'already exist'
        else
:
            self.__dict__[key]=value if __name__ == "__main__":
    g=get_try('value')
    g.value=4
    g.value1=3
    print g.__dict__
E:\python2.7.11\python.exe E:/py_prj/python_cookbook/chapter8.py
already exist
{'value1': 3, 'value': 'value'}
上面的代码中,首先判断赋值的对象是否已存在,如果存在则打印already exist
 

python cookbook第三版学习笔记十二:类和对象(三)创建新的类或实例属性的更多相关文章

  1. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  2. python cookbook第三版学习笔记十五:property和描述

    8.5 私有属性: 在python中,如果想将私有数据封装到类的实例上,有两种方法:1 单下划线.2 双下划线 1 单下划线一般认为是内部实现,但是如果想从外部访问的话也是可以的 2 双下划线是则无法 ...

  3. python cookbook第三版学习笔记十四:类和对象(五)代理类以及内存回收

    代理类: 代理类的作用其实有继承有些类似,如果你想将某个实例的属性访问代理到内部另外一个实例中去,可以用继承也可以用代理.来看下代理的应用: class A:     def spam(self,x) ...

  4. python cookbook第三版学习笔记十六:抽象基类

    假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...

  5. python cookbook第三版学习笔记十九:未包装的函数添加参数

    比如有下面如下的代码,每个函数都需要判断debug的是否为True,而默认的debug为False def a(x,debug=False): if debug: print('calling a') ...

  6. python cookbook第三版学习笔记十八:可由用户修改的装饰器

    定义一个属性可由用户修改的装饰器: 在前面的介绍中使用装饰器来包装函数,这一章来介绍下如何让用户调整装饰器的属性. 首先来看下代码: from functools import wraps,parti ...

  7. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions

    The ideal time to catch an error is at compile time, before you even try to run the program. However ...

  8. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  9. 《Linux命令、编辑器与shell编程》第三版 学习笔记---002

    <Linux命令.编辑器与shell编程>第三版 学习笔记---001 Linux命令.编辑器与shell编程 Shell准备 1.识别Shell类型 echo  $0 echo $BAS ...

随机推荐

  1. Java IO流之打印流与标准流

    一.打印流 1.1打印流特点与构造方法 1)PrintStream和PrintWriter类都提供了一系列重载的print和println方法来输出各种类型的数据. 2)PrintStream和Pri ...

  2. php 引用一点要小心使用

    今天遇见一个问题,我两次循环都是用的 foreach($temp as $k=>&$v){ // 用引用直接替换数组值 } foreach($temp2 as $k=>$v){ / ...

  3. asp.net core教程 (二)

    Asp.net Core环境设置 Asp.net Core环境设置 安装Microsoft Visual Studio 2015 Asp.Net Core是Asp.Net的一个重大的重新设计. 这个话 ...

  4. python不使用第三方变量,交换两个变量的值

    #不使用第三个变量交换两个变量的值 a=1 b=2 a,b=b,a#python的直接交换 #另一种交换方法 a=a+b#a=3 b=2 b=a-b#a=3 b=1 a=a-b#a=2 b=1 pri ...

  5. yield详解

    生成器generator 一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 yeild能暂时的保留函数的运行位置,每次 ...

  6. 学习总结------Servlet控制器的简单运用

    前言: 今天将简单的模拟 MVC模式 对Servlet控制器运行 若有不好或不对的地方,欢迎各位大神进行指导! 1.MVC模式(图) MVC全名是Model View Controller,是模型(m ...

  7. IBM新合作伙伴计划助力企业转型升级

        IBM作为老牌企业,一直在引领者技术方面的变革.当IBM再一次从自我革新开始,期望能够更快的将认知计算和云推广给自己的合作伙伴和用户们,以帮助他们在新的转型期内,能够快人一步.         ...

  8. 针对Oracle数据库表中的数据的常见操作

    1.查询表中所有数据 select * from 表名; 例:select * from stu; 2.查询的同时修改表中数据 select * from 表名  for update; 例:sele ...

  9. 让gdb能打印C++中的容器类型

    由于原生的gdb对vector,map等容器的支持不太好,所以找到了一个工具,将这个工具集成到gdb中,就可以实现map,vector等容器的内容的打印操作. 1.用vim将下方的代码拷贝到一个新的文 ...

  10. ajax数据请求3(数组json格式)

    ajax数据请求3(数组json格式) <!doctype html> <html> <head> <meta charset="utf-8&quo ...