• Python之旅的第24天(反射、包装、授权)


      今天主要的内容由getattr、hasattr、delattr、setattr引出反射问题,随后又补充了__import__、importlib,随后衍生了包装(利用类的派生)、授权(__getattr__)

    一、反射的引入

    # 关于反射,涉及四个hasattr、setattr、delattr、getattr
    # 反射是供类和对象进行使用的
    # 首先还是定义一个演示类
    # class Test:
    #     '定义了一个用于演示的类'
    #     country = 'China'
    #     def __init__(self,name):
    #         self.name = name
    #
    #     def niubi(self):
    #         print('%s是一个很牛逼的测试类')
    # 首先是关于hasattr,用于检测类中是否存在一个属性,返回bool值
    # print(hasattr(Test,'niubi'))   # True
    # print(hasattr(Test,'123'))     # False
    # 上面这种是直接针对类进行使用的,下面再看看实例化对象
    # t1 = Test('alex')
    # print(hasattr(t1,'niubi'))     # True
    # print(hasattr(t1,'country'))   # True
    # hasattr 以及后面即将演示的函数都要求后面属性名是一个字符串的形式
    
    # delattr 删除属性
    # print(t1.__dict__)    #{'name': 'alex'}
    # delattr(t1,'name')
    # print(t1.__dict__)    #{}
    # 记住实例化的对象的字典里面没有类的方法
    # print(Test.__dict__)
    # print(delattr(Test,'niubi'))
    # print(Test.__dict__)    #此时类的方法就被删除掉了
    
    # 关于getattr的使用,获取属性对应的值
    # t1 = Test('xiaoy')
    # print(getattr(t1,'country'))   #China
    # print(getattr(Test,'niubi'))   #<function Test.niubi at 0x00000178A7DE4488>
    # 返回的是一个方法的地址
    # print(getattr(Test,'niubi'))   #<function Test.niubi at 0x00000178A7DE4488>
    # getattr和delattr 的操作范围记得区分哦
    # delattr针对的是.__dict__对应的字典
    
    # 关于setattr的使用,输入对应的键值对,其实在底层就是实例化的过程
    # print(t1.__dict__)   # {'name': 'xiaoy'}
    # setattr(t1,'age',18)
    # print(t1.__dict__)   # {'name': 'xiaoy', 'age': 18}
    # 关于他们四个的直接作用是这些
    
    # 下面是关于__getattr__  __setattr__  __delattr__
    # __getattr__ 找不到调用的类时候会执行这个函数
    # __setattr__ 导入item的时候会执行
    # __delattr__ 删除字典内容的时候会执行
    
    class Test:
        '定义了一个用于演示的类'
        country = 'China'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def niubi(self):
            print('%s是一个很牛逼的测试类')
    
        def __getattr__(self, item):
            print('getattr执行了')
        def __delattr__(self, item):
            # print('delattr执行了')
            return (self.__dict__.pop(item))
    
    
        def __setattr__(self, key, value):
            print('setattr开始执行了')
            print('__setattr__执行')
            #         # self.key=value   # 这样会陷入持续的递归当中
            return self.__dict__[key]=value
    
    t1 = Test('alex',19)
    # 我们执行一个不存在的函数
    # t1.none()
    # print(t1.__dict__)   #{'age': 19, 'name': 'alex'}
    # del t1.name          #delattr执行了
    # print(t1.__dict__)   #{'age': 19, 'name': 'alex'}
    # 为啥这个地方没能删除成功呢,因为你修改了底层原有的代码
    # 我们重新修改一下
    # print(t1.__dict__)   #{'age': 19, 'name': 'alex'}
    # del t1.name          #delattr执行了
    # print(t1.__dict__)   #{'age': 19}
    # 这个时候就正常执行了del模式
    # del对应的就是__delattr__
    
    # setattr
    t1.y=10
    t1.x=3  # 设置属性的时候会触发——setattr———
    
    #我们修改了他的底层,就没办法保证正常的执行了

    二、动态导入

    module_t=__import__('m1.t')
    # 这种导入方法即使你的后面跟着很多他依然只会导入最开始的
    print(module_t)
    # module_t.t.test1()
    # from m1.t import *
    # from m1.t import test1,_test2
    #
    # test1()
    # _test2()
    import  importlib
    m=importlib.import_module('m1.t')
    # 导入到那一层就可以使用那一层
    print(m)
    m.test1()
    m._test2()

    三、包装,这个还是蛮神奇的,通过继承派生,我们可以在原生类上加上自己想要的功能

    class List(list):
        
        def append(self, p_object):
            if type(p_object) is str:
                # self.append(p_object)
                super().append(p_object)
            else:
                print('只能添加字符串类型')
    
        def show_midlle(self):
            mid_index=int(len(self)/2)
            return self[mid_index]
    
    
    # l2=list('hell oworld')
    # print(l2,type(l2))
    
    l1=List('helloworld')
    # print(l1,type(l1))
    # print(l1.show_midlle())
    l1.append(1111111111111111111111)
    l1.append('SB')
    print(l1)

    四、授权,我们刚才是通过继承实现了包装功能,现在就要使用牛逼的__getattr__

    import time
    class FileHandle:
        def __init__(self,filename,mode='r',encoding='utf-8'):
            # self.filename=filename
            self.file=open(filename,mode,encoding=encoding)
            self.mode=mode
            self.encoding=encoding
        def write(self,line):
            print('------------>',line)
            t=time.strftime('%Y-%m-%d %X')
            self.file.write('%s %s' %(t,line))
    
        def __getattr__(self, item):
            # print(item,type(item))
            # self.file.read
            return getattr(self.file,item)
    
    f1=FileHandle('a.txt','w+')
    # print(f1.file)
    # print(f1.__dict__)
    # print('==>',f1.read) #触发__getattr__
    # print(f1.write)
    f1.write('1111111111111111
    ')
    f1.write('cpu负载过高
    ')
    f1.write('内存剩余不足
    ')
    f1.write('硬盘剩余不足
    ')
    # f1.seek(0)
    # print('--->',f1.read())

    三、四部分没有增加相关解释逻辑,因为今天太晚了,明天我会增加上的,各位敬请期待

  • 相关阅读:
    关于面向对象和面象过程的一些感想
    面向对象之旅软件生命周期
    函数参数栈传递
    看完后停下来想想我们究竟在追求什么???
    面向对象之旅设计与设计原则
    [译]多重继承和虚继承的内存布局
    61条面向对象设计的经验原则
    数据库设计14个技巧(转)
    js的tween
    三、windows8 store
  • 原文地址:https://www.cnblogs.com/xiaoyaotx/p/12514973.html
Copyright © 2020-2023  润新知