[Python]小甲鱼Python视频第045课(魔法方法:属性访问 )课后题及参考解答

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 19 21:40:15 2019

@author: fengs
"""

"""
测试题:
0. 请问以下代码的作用是什么?这样写正确吗?(如果不正确,请改正)
def __setattr__(self, name, value):
        self.name = value + 1
        
在设置时被调用,但写得不正确,应该用映射/键值对的写法赋值 self.__dict__[name] = value + 1


1.自定义该类的属性被访问的行为,你应该重写哪个魔法方法?
    __getattribute__(self,name)
    
2. 在不上机验证的情况下,你能推断以下代码分别会显示什么吗?

3. 在不上机验证的情况下,你能推断以下代码分别会显示什么吗?

4. 请指出以下代码的问题所在:
        
"""


#测试题0
class Test(object):
    
    def __setattr__(self,name,value):
        self.__dict__[name] = value + 1
        #print(name)
        #self.name = value + 1
        
#test = Test()
#test.x = 1
#print(test.x)




#测试题2
class C:
    def __getattr__(self, name):
        print('-----')
        print(1)
        print('-----')
    def __getattribute__(self, name):
        print('-----')
        print(2)
        print('-----')
    def __setattr__(self, name, value):
        print('-----')
        print(3)
        print('-----')
    def __delattr__(self, name):
        print('-----')
        print(4)
        print('-----')

                
#c = C()
#c.x = 1
# 位置一,请问这里会显示什么?-------->   3
#print(c.x)
# 位置二,请问这里会显示什么?-------> 2 None


#测试题3
class C3:
    def __getattr__(self, name):
        print(1)
        return super().__getattr__(name)
    def __getattribute__(self, name):
        #print(2)
        print(name)
        return super().__getattribute__(name)
    def __setattr__(self, name, value):
        print(3)
        super().__setattr__(name, value)
    def __delattr__(self, name):
        print(4)
        super().__delattr__(name)

                
c3 = C3() #在__init__和 __new__时,其实__getattribute__就会被调用很多次了
#c3.x
#--------------------->  __getattr__ 并不存在, object没有 __getattr__这个魔方函数




class Counter:
    def __init__(self):
        self.counter = 0
    def __setattr__(self, name, value):       
        print(name)
        print(value)
        super().__setattr__(name, value)
        #self.counter += 1
    def __delattr__(self, name):
        self.counter -= 1
        print(self.counter)
        super().__delattr__(name)
#count = Counter()
#del count.counter

#self.counter = 0时会触发__setattr__,而+1操作要求counter已经定义才行,若在__setattr__中对counter进行操作,会引发递归调用


"""
动动手0
0. 按要求重写魔法方法:当访问一个不存在的属性时,不报错且提示“该属性不存在!”
"""

class dds0(object):
    
    
    #如果访问的属性存在,就不会调用__getattr__方法 可以直接改写成 return "该属性不存在"
    def __getattr__(self,name):
        if name not in self.__dict__:
            print("该属性不存在!")
            return None
        else:
            return super().__getattribute__(self,name)

#d = dds0()
#d.y = 10
#print(d.y)
#d.x


"""
1. 编写 Demo 类,使得下边代码可以正常执行
>>> demo = Demo()
>>> demo.x
'FishC'
>>> demo.x = "X-man"
>>> demo.x
'X-man'
"""
#我的写法
class Demo():
    def __init__(self):
        self.x = 'Fishc'
        
#小甲鱼的写法
class Demo2:
    def __getattr__(self, name):
        self.name = 'FishC'
        return self.name
demo = Demo2()
print(demo.x)
demo.x = "X-man"
print(demo.x)

#小甲鱼的写法也可以,第一次打印demo.x时,x不存在所以会调用 __getattr__,第二次打印已经有x了不会调用 __getattr__了
    
#demo = Demo()
#print(demo.x)
#demo.x = "X-man"
#print(demo.x)


"""
2. 修改上边【测试题】第 4 题,使之可以正常运行:编写一个 Counter 类,用于实时检测对象有多少个属性
"""
class dds2():
    def __init__(self):
        self.counter = 0
    def __getattribute__(self,name):
        if name == 'counter':
            self.__dict__[name] = len(self.__dict__) - 1
        return super().__getattribute__(name)
            
#d = dds2()
#d.x = 1
#d.y = 1
#print(d.counter)
#del d.x
#print(d.counter)
#del d.y 
#print(d.counter)

  

posted @ 2019-03-19 23:04  Alimy  阅读(420)  评论(0编辑  收藏  举报