小甲鱼零基础学习python_28 【python中魔法方法三:属性访问】

今天介绍以下四个访问属性的魔法方法:

    __getattribute__(self, item): 
    __getattr__(self, item):
    __setattr__(self, key, value):
    __delattr__(self, item):

这里写图片描述

先定义一个类用来做实验:

class C:
    def __getattribute__(self, item):  
        print('getattribute')
        return super().__getattribute__(item)   #默认继承object类
    def __getattr__(self, item):
        print('getattr')
    def __setattr__(self, key, value):
        print('setattr')
        super().__setattr__(key,value)
    def __delattr__(self, item):
        print('delattr')
        super().__delattr__(item)

1. 若访问一个不存在的属性时:

c1=C()
print(c1.x)

这里写图片描述

获取不存在属性的时候:getattribute比getattr先调用

先通过getattribute查找属性→找不到属性的时候采用getattr

2. 若访问一个存在的属性时:

c1.x=1
print(c1.x)

这里写图片描述

获取存在属性的时候:仅调用getattribute方法

3. 删除一个属性:

del c1.x

这里写图片描述


4. 用一个例子引入:死循环陷阱 → 矩形类:

#死循环陷阱  -- 矩形类例子

class Rectangle():
    def __init__(self, w=0, h=0):
        self.width=w
        self.height=h
    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




r1=Rectangle(4,5)
print(r1.getArea())

r1.square=10
print(r1.getArea())
print(r1.__dict__)

r1.width=5   #尝试只改变width属性
print(r1.getArea())
print(r1.__dict__)

这里写图片描述

错误原因:无限递归本类的_ _ setattr _ _,会错误 无限次调用本类的赋值方法;

解决办法1:调用基类方法(※推荐)

class Rectangle():
    def __init__(self, w=0, h=0):
        self.width=w
        self.height=h
    def __setattr__(self, name, value):
        if name=='square':
            self.width=value
            self.height=value
        else:
            super().__setattr__(name,value)   #推荐:方法一:调用基类方法

    def getArea(self):
        return self.width*self.height


r1=Rectangle(4,5)
print(r1.getArea())

r1.square=10
print(r1.getArea())
print(r1.__dict__)

r1.width=5   #尝试只改变width属性
print(r1.getArea())
print(r1.__dict__)

这里写图片描述

解决办法2:利用字典改变


class Rectangle():
    def __init__(self, w=0, h=0):
        self.width=w
        self.height=h
    def __setattr__(self, name, value):
        if name=='square':
            self.width=value
            self.height=value
        else:
            self.__dict__[name] = value   #方法二:利用字典改变
    def getArea(self):
        return self.width*self.height

r1=Rectangle(4,5)
print(r1.getArea())

r1.square=10
print(r1.getArea())
print(r1.__dict__)

r1.width=5      #尝试只改变width属性
print(r1.getArea())
print(r1.__dict__)

这里写图片描述


补充: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 deleteSize(self):
        del self.size
    x=property(getSize,setSize,deleteSize)
1. 赋值操作:
c1.x=100
2. 访问操作:
print(c1.x)
3. 删除操作:
del c1.x

其中x和size挂钩,改变或者删除x,size也随之改变或者删除!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值