零基础入门学习Python(23):魔法方法(3)属性访问

零基础入门学习Python(23):魔法方法(3)属性访问

在讲解今天的内容之前,我们先重写两个函数__str__()和__repr__(),第一个函数表示可以使用print()打印对象的值,第二个函数表示直接写出对象名就可以打印出对象的值。

>>> class Test:
        def __str__(self):
            return "Hello everyone."

>>> t1 = Test()
>>> t1                                 #直接写出t1得到它在内存中的位置
<__main__.Test object at 0x028859F0>
>>> print(t1)                          #需要调用print()才能打印出对象的值
Hello everyone.
>>> class Test:
        def __repr__(self):
            return "Hello everyone"

>>> t2 = Test()                        #重写__repr__()之后写出t2,则可以直接得到对象的值
>>> t2
Hello everyone

下面介绍一下Python属性访问的魔法方法:
1)__getattr__(self,name):定义当用户试图获取一个不存在的属性时的行为;
2)__getattribute__(self,name):定义当该类的属性被访问时的行为;
3)__setattr__(self,name,value):定义当一个属性被设置时的行为;
4)__delattr__(self,name):定义当一个属性被删除时的行为;

在访问属性的方法调用的时候,会先调用__getattribute__(self,name)方法,当属性不存在时再调用__getattr__(self,name)方法,下面通过举例验证一下。

>>> class TestAttr:
        def __getattribute__(self,name):           #分别重写属性访问的魔法方法
            print('getattribute...')
            return super().__getattribute__(name)  #返回值调用没重写时候的方法
        def __getattr__(self,name):
            print('getattr...')
        def __setattr__(self,name,value):
            print('setattr...')
            super().__setattr__(name,value)
        def __delattr__(self, name):
            print('delattr...')
            super().__delattr__(name)

>>> a1 = TestAttr()
>>> a1.x                                            #x属性不存在,则先调用__getattribute__()方法,再调用__getattr__()方法
getattribute...
getattr...
>>> a1.x = 2                                        #设置对象的x属性
setattr...
>>> a1.x                                            #再次访问x时,则直接调用__getattribute__()方法并显示出x的值
getattribute...
2
>>> del a1.x                                        #删除对象的x属性
delattr...

最后举一个例子:写一个矩形类,要求长宽默认为0,如果为一个叫square的属性赋值,说明是一个正方形,则长宽都等于square,最后计算矩形的面积。

>>> class Rectangle:
        def __init__(self, length = 0, width = 0):
            self.length = length             #赋值操作,会进到__setattr__()方法中
            self.width = width
        def __setattr__(self, name, value):  #重写__setattr__()方法
            if name == "square":             #先判断是否为正方形
                self.length = value
                self.width = value
            else:                            #如果不是,则调用未重写时候设置属性的方法
                super().__setattr__(name, value)

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

>>> r1 = Rectangle(2,3)                      #初始化长宽
>>> r1.getArea()
6
>>> r1.length = 5                            #可以只改变长或宽的值
>>> r1.getArea()
15
>>> r1.square = 7                            #给square赋值时,长宽相等
>>> r1.length
7
>>> r1.width
7
>>> r1.getArea()
49
>>> r1.__dict__                              #显示对象r1的属性
{'width': 7, 'length': 7}

由于对象的属性组成了一个字典类型的对象,所以设置属性时,除了可以使用super()方法之外,还可以利用字典的键值对给属性赋值,即super().__setattr__(name, value)这行代码可以改为self.__dict__[name] = value。当然,推荐大家使用super()方法。

零基础入门学习Python(22):魔法方法(2)算术运算

你可能感兴趣的:(类,python,魔法方法,属性访问)