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\n')
f1.write('cpu负载过高\n')
f1.write('内存剩余不足\n')
f1.write('硬盘剩余不足\n')
# f1.seek(0)
# print('--->',f1.read())

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

猜你喜欢

转载自www.cnblogs.com/xiaoyaotx/p/12514973.html
今日推荐