[Python]自学笔记27:魔法方法(5):属性访问

1.__getattr__(self,name)
定义当用户试图获取一个不存在的属性时的行为
2.__getattribute__(self,name)
定义当该类的属性被访问时的行为
3.__setattr__(self,name,value)
定义当一个属性被设置时的行为
4.__delattr__(self,name)
定义当一个属性被删除时的行为

以上方法皆可以重写

>>> class C:
	def __getattribute__(self,name):
		print('getattribute')
		return super().__getattribute__(name)   '''此处写return是因为getattribute方法需要一个返回值'''
	def __getattr__(self,name):
		print('getattr')      '''此处没有调用父类是因为getattr只有在属性不存在时被调用,在这里调用会出错'''
	def __setattr__(self,name,value):
		print('setattr')
		super().__setattr__(name,value)
	def __delattr__(self,name):
		print('delattr')
		super().__delattr__(name)

>>> c = C()
>>> c.x   '''此处试图访问c.x,调用getattibute,但是并不存在,所以又调用getattr'''
getattribute
getattr
>>> c.x = 1   '''此处直接给c.x赋值,所以直接调用setattr'''
setattr
>>> del c.x   '''此处删除了c.x,所以调用了delattr'''
delattr		

在这里插入图片描述

注意以下代码!

class Rectangle:
    def __init__(self,width=0,height=0):
        self.width = width
        self.height = height

    def __setattr__(self,name,value):
        if name == 'square':
            self.width = value
            self.height = value
        else:
            self.name = value
            '''此句会触发递归,因为当试图给一个属性width或height赋值时,
               便会调用setattr,又调用回来了,所以会触发递归。'''

            '''可以用以下两句中的任意一句进行修改!'''
            super().__setattr__(name,value) #此句是通过父类的setattr进行赋值,不会出现再调用回来的递归错误
            self.__dict__[name] = value  #此句是通过dict索引来改变name对应的属性的值(赋值)

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

请指出以下代码的问题
初学者重写属性魔法方法很容易陷入的一个误区就是木有“观前顾后”。

class Counter:
        def __init__(self):
                self.counter = 0 # 这里会触发 __setattr__ 调用
        def __setattr__(self, name, value):
                self.counter += 1
“““既然需要 __setattr__ 调用后才能真正设置 self.counter 的值,所以这时候 self.counter 还没有定义,所以没法 += 1,错误的根源。”””
                super().__setattr__(name, value)
        def __delattr__(self, name):
                self.counter -= 1
                super().__delattr__(name)

修改后:

>>> class Counter:
	k = []
	def __init__(self):
		self.counter = 0
	def __setattr__(self,name,value):
		if name != 'counter':
			if name not in self.k:
				self.counter += 1
				self.k.append(name)
		super().__setattr__(name,value)
	def __delattr__(self,name):
		self.counter -=1
		self.k.remove(name)
		super().__delattr__(name)

>>> c = Counter()
>>> c.x = 1
>>> c.counter
1
>>> c.y = 2
>>> c.counter
2
>>> del c.x
>>> c.counter
1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值