属性的魔法方法

__getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法

__setattr__(self,name,value):当一个属性被设置时,自动触发

__delattr__(self,name):当一个属性被删除时,自动触发

>>>class C:
  def __getattribute__(self,name):
    print('getattribute')
  def __getattr__(self,name):
    print('getattr')
  def __setattr__(self,name,value):
    print('setattr')
  def __delattr__(self,name):
    print('delattr')
>>>c = C()
>>>c.x
getarrribute

此处没有调用并打印getattr的原因,要从实例对象属性的访问顺序说起:

首先调用getattribute -> 然后在实例对象中查找 -> 继续在实例的类中查找 -> 最后在父类中查找 -> 均无法找到时调用getattr方法

是要当所有流程都走完,都没找到该属性,才会调用getattr方法,但由于重写了getattribute方法,所以需要用super()函数来调用父类

>>>class C:
  def __getattribute__(self,name):
    print('getattribute')
    super().__getattribute__(name)
  def __getattr__(self,name):
    print('getattr')
  def __setattr__(self,name,value):
    print('setattr')
  def __delattr__(self,name):
    print('delattr')
>>>c = C()
>>>c.x
getarrribute
getattr
>>>c.x = 1
setattr
>>>c.x
getarrribute
1
>>>del c.x
delattr

__getattr__(self,name):当访问一个不存在的属性时,自动触发,默认返回值为None

正常情况下,当我们调用类的属性时,如果不存在这个属性会报错

但如果我们在类中重写了__getattr__方法,当用户访问不存在的类的属性时,python会自动调用__getattr__来获得在类中重写的属性或异常

>>>class Rectangle:
  def __init__(self,height=5):
    self.height = height
  def __getattr__(self,name):
    if name == 'width':
      width = 10
      return width
    raise AttributeError('This attribute does not exist')
>>>r = Rectangle()
>>>r.height #调用类中存在的属性,不会触发__getattr__方法
5
>>>r.width #调用类中不存在的属性,触发__getattr__方法并获得属性
10
>>>r.name #调用类中不存在的属性,触发__getattr__方法并抛出异常
AttributeError: This attribute does not exist

这里要注意一个容易产生死循环的问题,比如例子:

>>>class Rectangle:
  def __init__(self,widt = 0,height = 0):
    self.width = width #此处有给属性赋值的操作,所以会自动触发__setattr__
    self.height = height
  def __setattr__(self,name,value):
    if name == 'square':
      self.width = value
      self.height = value
    else:
      self.name = value #而在__setattr__方法中又存在赋值操作,所以产生无限递归
  def getArea(self):
    return self.width * self.height
修改方法:将else分支的语句改为super().__setattr__(name,value),此处直接调用父类的方法,免去赋值操作,就不会再产生递归
>>>r1 = Rectangle(4,5)
>>>r1.getArea()
20
>>>r1.square = 10
>>>r1.__dict__ #以列表的形式显示该对象的所有属性
{'width': 10, 'height': 10}
>>> r1.getArea()
100

Python笔记(二十六)_魔法方法_属性的魔法方法的更多相关文章

  1. python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码

    python3.4学习笔记(二十六) Python 输出json到文件,让json.dumps输出中文 实例代码 python的json.dumps方法默认会输出成这种格式"\u535a\u ...

  2. 使用Typescript重构axios(二十六)——添加HTTP授权auth属性

    0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...

  3. Python笔记(二十四)_魔法方法_运算符的魔法方法

    算数运算方法 .反运算方法 以对象A+对象B为例,都是将A作为self值,而B作为other值传入__add__(self,other)方法: 当用户输入A+B,就会调用重写的add方法: >& ...

  4. [Python笔记]第十六篇:web框架之Tornado

    Tornado是一个基于python的web框架,xxxxx 安装 python -m pip install tornado 第一个Tornado程序 安装完毕我们就可以新建一个app.py文件,放 ...

  5. Java基础学习笔记二十六 JDBC

    什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库,J ...

  6. angular学习笔记(二十八-附1)-$resource中的资源的方法

    通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,$save,$delete,$remove,可以直接调用来保存该资源: 比如有一个$resour ...

  7. Python笔记(二十八)_魔法方法_迭代器

    迭代器用于遍历容器中的数据,但它不是容器,它是一个实现了__next__方法的对象 与迭代器相关的内置函数: iter(): 将一个对象转换成一个迭代器 next(): 访问迭代器中的下一个变量,直到 ...

  8. Python笔记(二十二)_魔法方法_基本魔法方法

    __init__(self[,...]) __init__和__new__组成python的构造器,但__init__更多的是负责初始化操作,相当于一个项目中的配置文件,__new__才是真正的构造函 ...

  9. Python笔记(二十五)_魔法方法_描述符

    描述符的属性方法 __get__(self, instance, owner): 用于访问属性,返回属性的值 __set__(self, instance, value): 用于给属性赋值时,返回属性 ...

随机推荐

  1. java 技术分享

    http://www.ccblog.cn/99.htm http://www.ccblog.cn/100.htm http://www.ccblog.cn/101.htm http://www.ccb ...

  2. XIB约束布局问题(button)

    button默认不给宽度:系统Xib自动适配,最小宽度30.在使用宽度计算时,无法小于这个值

  3. readline和xreadline的区别

    readline就是直接读取一行 xreadline是生成了一个生成器,遍历的时候才真正生成具体的内容 与range和xrange的区别一样 print range() # 直接创建所有的元素 pri ...

  4. C# List<Object>值拷贝

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Run ...

  5. Java并发——原子变量和原子操作

    很多情况下我们只是需要一个简单的.高效的.线程安全的递增递减方案.注意,这里有三个条件:简单,意味着程序员尽可能少的操作底层或者实现起来要比较容易:高效意味着耗用资源要少,程序处理速度要快:线程安全也 ...

  6. 02MySQL数据库

    1.MySQL启动和关闭 2.登录MySQL数据库 MySQL是一个需要账户名密码登录的数据库,登陆后使用,它提供了一个默认的root账号,使用安装时设置的密码即可登录. 格式1:cmd>  m ...

  7. spring security基本知识(二) 自定义认证

    配置自定义的用户存储 我们在 SecurityConfig 的配置类中 重写了 configure(AuthenticationManagerBuilder auth) 方法,我们可以通过 Authe ...

  8. Mixly-指令

    串口: 向串口监视器输出数据       十进制       Serial.println(ir_item,HEX); 向串口监视器输出数据---十六进制 通信: 接收11脚的红外信号,把接收到的数据 ...

  9. rocketmq设计

    # 设计(design) 1 消息存储 消息存储是RocketMQ中最为复杂和最为重要的一部分,本节将分别从RocketMQ的消息存储整体架构.PageCache与Mmap内存映射以及RocketMQ ...

  10. 【bzoj2002】弹飞绵羊

    题目 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数k ...