通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过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_魔法方法(四):属性访问的更多相关文章

  1. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  2. 零基础学习python_魔法方法(41-48课)(迭代器)

    接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...

  3. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  4. ie8 报错:意外地调用了方法或属性访问

    在某场景中一句简单的js: $("#changeOption").text("增加"); 在 IE8 下面报错:'意外地调用了方法或属性访问' 改成:$(&qu ...

  5. python基础教程_学习笔记11:魔法方法、属性和迭代器

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/31417309 魔法方法.属性和迭代器 在pyth ...

  6. python学习笔记之七:魔法方法,属性

    在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...

  7. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器

    准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...

  8. 【Python045-魔法方法:属性访问】

    一.属性的几种访问方式 1.类.属性名 >>> class C: def __init__(self): self.x = 'X-man' >>> c = C() ...

  9. python_魔法方法(五):描述符和定制序列

    描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...

随机推荐

  1. properties使用

    properties可以load store 注释可以采用 "#" 或者"!" 分隔采用"="或者":" 分行采用&qu ...

  2. Operating System-Process(1)什么是进程&&进程的创建(Creation)&&进程的终止(Termination)&&进程的状态(State)

    本文阐述操作系统的核心概念之一:进程(Process),主要内容: 什么是进程 进程的创建(Creation) 进程的终止(Termination) 进程的状态(State) 一.什么是进程 1.1 ...

  3. rsync 端口更换(默认873)

    一般使用默认端口的话, 在服务端的启动命令为: /usr/bin/rsync --address=192.168.1.23 --daemon 如果在客户端需要换另外的端口侦听, 则使用 /usr/bi ...

  4. SQL常用语法及规则-表格的操作

    一.规则和标准 1)每一行SQL语句结尾,加分号: 2)所创建的对象,名字用反引号(不是引号,与~同一个键): 3)一般关键字或保留字要大写: 4)两个中划线 + 空格(-- ),后面的语句为注释语句 ...

  5. Linux根据端口查看进程

    若不知道具体目录,可以根据端口查找,查看端口22000的信息: sudo lsof -i:22000 RelaySvr 4322 root   13u  IPv4 75680495      0t0  ...

  6. wpf dataGrid 选中行 失去焦点时 的背景颜色的更改

    关于 wpf dataGrid 选中行 失去焦点时 的背景颜色的更改.很简单的方式,在datagrid的resource中更改InactiveSelectionHighlightBrushKey属性的 ...

  7. docker 部署服务时,node(结点)显示no such image

    1. 问题描述 ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 9cn5x84lnmga getstartedlab_web.1 ...

  8. numpy和matlab计算协方差矩阵的不同(matlab是标准的,numpy相当于转置后计算)

    matlab是标准的,numpy相当于转置后计算 >> x = [2,0,-1.4;2.2,0.2,-1.5;2.4,0.1,-1;1.9,0,-1.2] x = 2.0000    0 ...

  9. oracle 实现 自增主键功能

    转自:https://blog.csdn.net/zxh2075/article/details/78488141 之前有一项工作是将mysql的数据库实现转移到oracle,遇到了自增主键实现的问题 ...

  10. 异常:Project configuration is not up-to-date with pom.xml解决方案

    转自:https://www.cnblogs.com/zhujiabin/p/6343423.html 1. Description    Resource    Path    Location   ...