魔术方法反射

反射

运行时,区别于编译时,指的是程序被加载到内存中执行的时候。
反射,reflection,指的是运行时获取类型定义信息。
一个对象能够在运行时,像照镜子一样,反射出其类型信息。
简单说,在Python中,能够通过一个对象,找出其type、class、attribute或method的能力,称为反射或者自 省。
具有反射能力的函数有 type()、isinstance()、callable()、dir()、getattr()等

反射相关的函数和方法
需求

内建函数意义
getattr(object,name[,default])通过name返回object的属性值,当属性不存在,将使用default返回,如果没有default,则抛出AttributeError.name必须为字符串
setattr(object,name,value)object的属性存在,则覆盖,不存在,新增
hasattr(object,name)判断对象是否有这个名字的属性,name必须为字符串
class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
        
    def __str__(self):
        return '{},{}'.format(self.x,self.y)
    
    def show(self):
        print(self.x,self.y)

        
p = Point(3,4)
p2 = Point(5,6)
print(getattr(p,'z',1000))

#动态增加方法
#为类增加方法
if not hasattr(Point,'add'):
    setattr(Point,'add',lambda self,other:Point(self.x+other.x,self.y+other.y))
print(p.add(p2))#绑定

#为实例增加方法,未绑定
if not hasattr(p,'sub'):
    setattr(p,'sub',lambda self,other:Point(self.x-other.x,self.y-other.y))

print(p.sub(p2,p))

print(Point.__dict__)
print(p.__dict__)

这种动态增删属性的方式是运行时改变类或者实例的方式,但是装饰器或Mixin都是定义时就决定了,因此反射能力具有更大的灵活性.

反射相关的魔术方法
__getattr__(),__setattr__(),__delattr__()这三个魔术方法,分别测试者三个方法

class Base:
    n = 0

class Point(Base):
    z = 6
    
    def __init__(self,x,y):
        self.x = x
        self.y = y
    
    def show(self):
        print(self.x,self.y)
    
    def __getattribute__(self,item):
        return object.__getattribute__(self,item)
    
    def __getattr__(self,item):
        return item
    
    def __setattr__(self,key,value):
        print('{}{}'.format(key,value))
        self.__dict__[key] = value
    

p = Point(1,2)
print(p.x)
print(p.y)
print(p.__dict__)
print(p.z)

__getattr__()
实例属性会按照继承关系找,如果找不到,就会执行__getattr__()方法,如果没有这个方法,就会抛出AttributeError异常表示找不到属性

查找属性顺序为:
instance.__dict__ --> instance.__class__.__dict__ --> 继承的祖先类(直到object)的__dict__ —找不到–> 调 用__getattr__()

__setattr__()
实例通过.点号设置属性,例如self.x = x属性赋值,就会调用__setattr__(),属性要加到实例的__dict__中,就需要自己完成
__setattr__()方法,可以拦截对实例属性的增加 修改操作,如果要设置生效,需要自己操作实例的__dict__

__delattr__()

class Point():
    Z = 6
    
    def __init__(self,x,y):
        self.x = x
        self.y = y
    
    def __delattr__(self,item):
        print(item)
    
p = Point(1,2)
p.z = 10
del p.z
print(p.__dict__)
print(Point.__dict__)
del Point.Z
print(Point.__dict__)

可以阻止通过实例来删除属性的操作,但是通过类依然可以删除属性

__getattribute__

实例的所有的属性访问,第一个都会调用__getattribute__方法,它阻止了属性的查找,该方法应该返回(计算后的值)或者抛出一个AtteributeError异常

  • 它的return值作为属性查找的结果
  • 如果抛出AttributeError异常,则会直接调用 __getattr__ 方法,因为表示属性没有找到。
class Base:
    n = 0

class Point(Base):
    z = 6
    
    def __init__(self,x,y):
        self.x = x
        self.y = y
    
    def __getattribute__(self,item):
        return object.__getattribute__(self,item)
    
    def __getattr__(self,item):
        return item


p = Point(1,2)
print(p.x)
print(p.y)
print(p.__dict__)
print(p.z)

__getattribute__方法中为了避免在该方法中无限的递归,它的实现应该永远调用基类的同名方法以访问需要的任何属性,例如object.__getattribute__(self,item)

注意,除非你明确地知道 __getattribute__ 方法用来做什么,否则不要使用它

魔术方法意义
__getattr__()当通过搜索实例、实例的类及祖先类查不到属性,就会调用此方法
__setattr__()通过 . 访问实例属性,进行增加、修改都要调用它
__delattr__当通过实例来删除属性时调用此方法
__getattribute__实例所有的属性调用都从这个方法开始

属性查找顺序
实例调用__getattribute__() --> instance.__dict__ --> instance.__class__.__dict__ --> 继承的祖先类(直到 object)的__dict__ --> 调用__getattr__()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python的魔术方法是以双下划线开头和结尾的方法,也被称为Magic Method(魔术方法)。这些方法在Python中具有特殊的功能和行为。魔术方法包括类的初始化方法__init__、比较方法、数值处理方法、普通算术操作符等等。魔术方法的作用是为了增强类的功能和灵活性,使对象能够具有更复杂的行为和操作。比如__init__方法用于初始化一个对象的状态,__str__方法定义了对象在被str()函数调用时的行为,__repr__方法定义了对象在被repr()函数调用时的行为等等。通过合理使用魔术方法,我们可以更好地控制和定制自己的类和对象的行为。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [python的魔术方法大全](https://blog.csdn.net/qq_40236497/article/details/125539436)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [Python魔术方法详解](https://download.csdn.net/download/weixin_38501610/12879041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值