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__(). ...
随机推荐
- DSP基础
CCS V5的使用 CCS安装与设置
- 发布倒计时!JDK11为我们带来哪些新特性?
今年7月底,JDK11已经进入了Rampdown Phase Two阶段,这标志着该版本所有特性已经被冻结,不会有新的JEP会加入版本中. 这一阶段将会修复P1–P2级BUG,之后,JDK11预定于今 ...
- Python-实现socket简单地连续发数据
只需用while条件判断来实现 服务器端 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import socket serv ...
- 使用雅虎YUI Compressor压缩JS过程心得记录
对待发布的项目进行测试时,发现js下载量比较大,从jquery的min版想到了压缩项目中的js文件.很简单的google之(在此,强调一下google的重要性),搜到一个叫做YUI Compresso ...
- Oracle中生成UUID
Oracle中生成跨系统的唯一识别符UUID非常方便,比生成序列还简单,直接用sys_guid()就行, 例如select sys_guid() from dual 会产生一个跟MAC地址.生成时间相 ...
- CCNet说明文档
1.CCNet安装步骤 1) 安装CCNet服务器端:CruiseControl.NET-1.8.5.0-Setup.exe 2) 安装CCNet客户端:CruiseControl.NET ...
- Java 数据类型间的相互转化
Java中常见基本数据类型包括(String除外[引用]) Date(int year,int month,int day,int hour,int minute,int sec); String 格 ...
- CentOS7下源码安装5.6.23
清理CentOS7下的MariaDB. [root@localhost ~]#rpm -qa | gremp mariadb [root@localhost ~]# rpm -e --node ...
- CentOS 7 配置 mariadb
一.安装mariadb : yum groupinstall mariadb mariadb-client -y 二.启动(设置开机启动)服务 : systemctl start (enabl ...
- Learning Python 006 list(列表) 和 tuple(元组)
Python list(列表) 和 tuple(元组) list 列表 Python内置的一种数据结构.list:一种有序的集合,可以随时添加和删除其中的元素. list的用法 定义list > ...