python_魔法方法(四):属性访问
通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧
>>> class A():
def __init__(self):
self.x = 'XYZ-xyz' >>> a = A()
>>> a.x
'XYZ-xyz'
>>> getattr(a,'x','没有这个属性')
'XYZ-xyz'
>>> getattr(a,'z','没有这个属性')
'没有这个属性'
>>> setattr(a,'z','red')
>>> getattr(a,'z','red')
'red'
>>> delattr(a,'x')
>>> a.x
Traceback (most recent call last):
File "<pyshell#12>", line , in <module>
a.x
AttributeError: 'A' object has no attribute 'x'
在来介绍一个property()函数的用法,这个property()使我们可以用属性去访问属性,还是会来看个例子
>>> class C():
def __init__(self,size = 10):
self.size = size
def getsize(self):
return self.size
def setsize(self,value):
self.size = value
def delsize(self):
del self.size
x = property(getsize,setsize,delsize) >>> c = C()
>>> c.x
10
>>> c.x = 12
>>> c.x
12
>>> c.size
12
>>> del c.x
>>> c.size
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
c.size
AttributeError: 'C' object has no attribute 'size'
关于属性访问,肯定也有相应的魔法方法来管理。通过对这些魔法方法的重写,照样可以随心所欲控制对象的属性访问。
来介绍下属性相关的魔法方法:
魔法方法 | 含义 |
__getattr__(self,name) | 定义当用户试图获取一个不存在的属性十的行为 |
__getattribute__(self,name) | 定义当该类的属性被访问时的行为 |
__setattr__(self,name) | 定义当一个属性被设置时的行为 |
__delattr__(self,name) | 定义当一个属性被删除时的行为 |
好了,我们先来做个测试:
>>> class A():
def __getattribute__(self,name):
print('getattribute')
#使用super()调用object基类__getattribut__()方法
return super().__getattribute__(name)
def __setattr__(self,name,value):
print('setattr')
super().__setattr__(name,value)
def __delattr__(self,name):
print('delattr')
super().__delattr__(name)
def __getattr__(self,name):
print('getattr') >>> a = A()
>>> a.x
getattribute
getattr
>>> a.x = 1
setattr
>>> a.x
getattribute
1
>>> del a.x
delattr
>>> setattr(a,'y','yellow')
setattr
这几个魔法方法在使用的时候要注意,防止进入死循环陷阱,下面通过实例来说明,写一个矩形类(Rectangle),默认有宽(width)和高(height)两个属性;如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时高宽都应该等于边长
>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
else:
self.key = value
def getArea(self):
return self.width *self.height >>> r1 = Rectangle(4,5)
Traceback (most recent call last):
File "<pyshell#65>", line 1, in <module> r1 = Rectangle(4,5)
File "<pyshell#64>", line 3, in __init__ self.width = width
File "<pyshell#64>", line 10, in __setattr__ self.key = value
File "<pyshell#64>", line 10, in __setattr__ self.key = value
File "<pyshell#64>", line 10, in __setattr__ self.key = value
[Previous line repeated 325 more times]
File "<pyshell#64>", line 6, in __setattr__ if key == 'square':
RecursionError: maximum recursion depth exceeded in comparison
出现这个循环的原因在于调用了__init__()方法,在这里给self.width和self.height分别初始化赋值。一旦发生赋值操作就会自动触发__setattr__()魔法方法,width和height两个属性被赋值,于是执行了else的下边的语句,就又变成了self.width=value,那么久相当于又触发了__setattr__()魔法方法,造成了死循环。
解决方法一,就是和刚才的一样,使用super()来调用基类的__setattr__(),那么这样就依赖基类的方法来实现赋值:
>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
else:
super().__setattr__(key,value)
def getArea(self):
return self.width *self.height >>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100
解决方法二:给特殊属性__dict__赋值。对象有一个特殊的属性,__dict__,它的作用是以字典的形式显示出当前对象的所有属性以及相对于的值。
调用死循环的类
>>> r1.__dict__
{'width': 10, 'height': 10}
>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
else:
self.__dict__[name] = value
>>> r1 = Rectangle(4,5)
python_魔法方法(四):属性访问的更多相关文章
- Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )
通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...
- 零基础学习python_魔法方法(41-48课)(迭代器)
接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...
- 【python学习笔记】9.魔法方法、属性和迭代器
[python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...
- ie8 报错:意外地调用了方法或属性访问
在某场景中一句简单的js: $("#changeOption").text("增加"); 在 IE8 下面报错:'意外地调用了方法或属性访问' 改成:$(&qu ...
- python基础教程_学习笔记11:魔法方法、属性和迭代器
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/31417309 魔法方法.属性和迭代器 在pyth ...
- python学习笔记之七:魔法方法,属性
在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...
- 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器
准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...
- 【Python045-魔法方法:属性访问】
一.属性的几种访问方式 1.类.属性名 >>> class C: def __init__(self): self.x = 'X-man' >>> c = C() ...
- python_魔法方法(五):描述符和定制序列
描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...
随机推荐
- HDOJ1025(最长上升子序列)
Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65 ...
- Boost库之asio io_service以及run、run_one、poll、poll_one区别
一.io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数.Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,r ...
- js获取集合对象的个数
代码: var t={"a":"1","b":'2'}; alert(Object.keys(t).length); 用处:可用于集合对象的 ...
- JavaScript设计模式--桥梁模式--引入
1.使用情况 (1)事件的监控 #1,利用页面的button来选择宠物的例子(思路) button.addEvent(element,"click",getPetByBame); ...
- JavaScript原型模式(prototype)
1.原型是一个对象,其他对象可以通过它实现属性的继承所有对象在默认的情况下都有一个原型,因为原型的本身也是对象,所以一个类的真正原型是被类的内部[prototype]属性所指出.每个函数都有一个属性叫 ...
- PID控制及整定算法
一.PID控制算法 PID是比例.积分.微分的简称,PID控制的难点不是编程,而是控制器的参数整定.参数整定的关键是正确地理解各参数的物理意义,PID 控制的原理可以用人对炉温的手动控制来理解.阅读本 ...
- JavaScript高级程序设计学习笔记第十五章--使用Canvas绘图
一.基本用法 1.要使用<canvas>元素,必须先设置其 width 和 height 属性,指定可以绘图的区域大小.能通过 CSS 为该元素添加样式,如果不添加任何样式或者不绘制任何图 ...
- Spinner 通过XML形式绑定数据时 无法从String.xml中读取数组
在android应用程序中,通过XML形式给Spinner绑定数据,如果把数组放在系统的string.xml文件里,那么就有可能在运行时无法找到,导致程序异常结束,解决方法是自建一个XML文件来存放数 ...
- spring 4.0 注解数据验证1
通常情况下,数据验证都分为前台验证,后台验证.并且前台JS验证是肯定有的,那么其实验证的错误信息根本不必通过后台传过去,哪怕就是想国际化,前台JS也能够胜任. 如果前台验证足够了,那么如果还有不正确的 ...
- java连接sqlserver2005数据库
java连接sqlserver2005数据库 首先得下载驱动程序到微软网站下载Microsoft JDBC Driver 4.0 for SQL Server 下载地址 :http://msdn. ...