human
(4) __getattr__和__setattr__   
拦截（intercept）对象的所有属性访问是可能的，这样可以用旧式类实现属性。为了在访问属性的时候可以执行代码，必须使用一些特殊方法。下面的4种方法提供了需要的功能（在旧式类中只需要后3个）
a. __getattribute__(self,name):当属性name被访问时自动被调用（只能在新式类中使用）；
b. __getattr__(self,name):当属性name被访问且对象没有相应的属性时被自动调用；
c. __setattr__(self,name,value): 当试图给属性name赋值时会被自动调用；
d. __delattr__(self,name): 当试图删除属性name时会被自动调用。
尽管和使用property函数相比有点复杂（而且在某些方面效率更低），但是这些特殊方法是很强大的，因为可以对处理很多属性的方法进行再编码。   
下面还是Rectangle的例子，但这次使用的是特殊方法："
Please write code following the instructions in jupyter notebook style.

=====
Write me a code to (4) __getattr__和__setattr__  and the other steps required?
assistant
#Here is code to (4) __getattr__和__setattr__  and the other steps required.

class Rectangle:
    def __init__(self):
        self.width=0
        self.height=0
    def __setattr__(self,name,value):
        if name =='size':
            self.width,self.height=value
        else:
            self.__dict__[name]=value
    def __getattr__(self,name):
        if name =='size':
            return self.width,self.height
        else:
            raise AttributeError

w=Rectangle()
w.size

w.__dict__

w.size=(2,6)
w.size

w.width

hasattr(w,'size')

w.age=28
w.age

w.__dict__