面向对象进阶一

来源:互联网 发布:FGO黑贞各礼装伤害数据 编辑:程序博客网 时间:2024/06/06 10:07

反射

通过字符串的形式操作对象相关的属性
四个可以实现自省的函数:hasattr、getattr、setattr、delattr

class People:    country = 'China'    def __init__(self,Name):        self.name = Name

hasattr

p = People('spring')print(p.__dict__)print(hasattr(p,'country'))print(hasattr(p,'__doc__'))print(hasattr(p,'name'))print(hasattr(p,'__init__'))print(hasattr(People,'country'))

getattr

res = getattr(p,'country')print(res)res = getattr(p, 'age', '没有设定age')print(res)res = getattr(People, 'country')print(res)

setattr

p.age = 18print(p.age)print(p.__dict__)setattr(p, 'age', 28)print(getattr(p, 'age'))setattr(People,'country','USA')print(getattr(People,'country'))

delattr

print(hasattr(p, 'age'))delattr(p, 'age')  #res = getattr(p, 'age', '没有设定age') # 找不到可以设个返回值,不设定找不到会报错。print(hasattr(p, 'age'))

使用反射的好处:


1.通过字符串来导入模块,动态导入模块

#不推荐这个m = __import__('time')print(m.time())#推荐方法import importlibm = importlib.import_module('time')print(m.time())

2.可插拔机制,实现可插拔机制

#moduleclass FtpClient:    def __init__(self, addr):        print('正在连接服务器[%s]'%addr)        self.addr = addr    # def get(self):    #     print('get')
from module import FtpClientf1 = FtpClient('192.168.1.1')if hasattr(f1, 'get'):    func_get = getattr(f1, 'get')    func_get()else:    print('---->不存在此方法')

反射当前模块属性(成员)

import sysx = 22class Foo:    passdef s1():    print('s1')def s2():    print('s2')this_module = sys.modules[__name__]print(this_module)print(hasattr(this_module,'s1'))print(this_module.s1)

__setattr__, __delattr__, __getattr__

#__setattr__, __delattr__, __getattr__class Foo:    def __init__(self,Name):        self.name = Name    def __setattr__(self, key, value):        print('---setattr-----key: %s value: %s'%(key, value))        self.__dict__[key] = value    def __delattr__(self, item):        print('------delattr-----item: %s'%item)        # self.__dict__.pop(item)        del self.__dict__[item]    def __getattr__(self, item):        print('----getattr----item: %s'%item)#setattrcc = Foo('spring')print(cc.__dict__)print(cc.name)cc.__dict__['age'] = 166print(cc.age)#delattrprint(cc.__dict__)del cc.ageprint(cc.__dict__)#getattr  属性不存在才会运行 和getattr() 结合使用print('!'*100)print(cc.zz)

定制自己的数据类型

1 基于继承标准的数据类型来定制数据类型

class List(list):    def append(self, object: int):        if not isinstance(object,int):            raise TypeError('must be int')        super().append(object)        #list.append(self,object)    def insert(self, index: int, object: int):        if not isinstance(object, int):            raise TypeError('must be int')        super().insert(index, object)cc = List([1,2,3])print(cc)#cc.append('3')cc.append(33)print(cc)cc.insert(0,22)print(cc)

2 授权的方式定制数据类型

import timeclass Open:    def __init__(self, file_path, m='r', encode='utf-8'):        self.x = open(file_path, mode=m, encoding=encode)        self.file_path = file_path        self.encoding = encode    def write(self, line):        print('写入: ', line)        t = time.strftime('%Y-%m-%d %X')        self.x.write('%s %s'%(t, line))    def __getattr__(self, item):        return getattr(self.x, item)f = Open('a.txt', m='a+')f.x.write('sss\n')f.write('zzz\n')f.seek(0)print(f.read())class List:    def __str__(self):        return str(self.cont)    def __init__(self,cont):        self.cont = cont    def append(self,value):        if not isinstance(value, str):            raise TypeError('must be str')        self.cont.append(value)    @property    def mid(self):        if len(self.cont) == 1 or len(self.cont) == 0:  #如果list为口活着只有一个元素返回list本身            return self.cont        a, b = divmod(len(self.cont), 2)        if b != 0:            return self.cont[a+1]    #如果奇数返回中间数        else:            return self.cont[a:a+2]  #如果是偶数返回中间的2个数    def __getattr__(self, item):     #其余方法都使用list自带        return getattr(self.cont,item)cc = List(['b','a','c','d'])print(cc.mid)cc.append('z')cc.sort()print(cc)
0 0
原创粉丝点击