Python面向对象中反射

 

目录

 

反射是什么?

Python中的反射主要方法:

方法的使用

类也是对象

反射当前模块成员

动态导入模块(基于反射当前模块成员)

__setattr__、__delattr__、__getattr__方法

二次加工标准类型(包装)

授权

isinstance和issubclass方法

item方法

改变对象的字符串显示


反射是什么?

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,在python中一切皆对象(类,实例,模块等等都是对象),那么我们就可以通过反射的形式操作对象相关的属性。

Python中的反射主要方法:

1.hasattr(object,name)

判断对象中有没有一个name字符串对应的方法或属性

2.getattr(object, name, default=None)

获取对象name字符串属性的值,如果不存在返回default的值

3.setattr(object, key, value)

设置对象的key属性为value值,等同于object.key = value

4.delattr(object, name)

删除对象的name字符串属性

方法的使用

class Map:
    f1 = '召唤师峡谷'
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr
    def from1(self):
        print('%s来自%s'%(self.name,self.addr))
    def from2(self):
        print('%s选手是%s'%(self.addr,self.name))

b1 = Map('盖伦','上路')
#检测是否含有某属性;
print(hasattr(b1,'name'))       #True
print(hasattr(b1,'from1'))      #True

#获取属性;
n = getattr(b1,'name')
print(n)                        #盖伦
func = getattr(b1,'from1')
func()                          #盖伦来自上路
#getattr(b1,'abcsdf')            #报错
print(getattr(b1,'xxxxxxx','不存在'))  #不存在

#设置属性;
setattr(b1,'ADC','下路')
print(b1.__dict__)              #{'name': '盖伦', 'addr': '上路', 'ADC': '下路'}
setattr(b1,'贵族','VN'+'奥巴驴')
print(b1.__dict__)              #{'name': '盖伦', 'addr': '上路', 'ADC': '下路', '贵族': 'VN奥巴驴'}

#删除属性
delattr(b1,'addr')
print(b1.__dict__)              #{'name': '盖伦', 'ADC': '下路', '贵族': 'VN奥巴驴'}
delattr(b1,'ADC')
print(b1.__dict__)              #{'name': '盖伦', '贵族': 'VN奥巴驴'}

类也是对象

class Foo(object):
    test = 'hello world!'
    def __init__(self):
        self.name = 'xuan'

    def func(self):
        return 'func'
    @staticmethod
    def bar():
        return 'bar'

print(getattr(Foo,'test'))      #hello world!
print(getattr(Foo,'func'))      #<function Foo.func at 0x000001FF2457E048>
print(getattr(Foo,'bar'))       #<function Foo.bar at 0x000001FF2457E0D8>

反射当前模块成员

import sys
def s1():
    print("s1")

def s2():
    print("s2")

this_module = sys.modules[__name__]

print(hasattr(this_module,'s1'))        #True
print(getattr(this_module,'s2'))        #<function s2 at 0x0000016B892E5EE8>
foo = getattr(this_module,'s2')
foo()                                   #s2

动态导入模块(基于反射当前模块成员)

t.py

Dy_module.py

h = __import__('m1.t')      #=====================
print(h)         #<module 'm1' (namespace)>
h.t.test1()      #test1
h.t.test2()      #test2

import importlib
k = importlib.import_module('m1.t')
print(k)        #<module 'm1.t' from 'G:\\pycharm\\Exercise\\2019.08\\m1\\t.py'>
k.test1()       #test1
k.test2()       #test2

__setattr__、__delattr__、__getattr__方法

class Foo:
    def __init__(self,name):
        self.name = name

    def __getattr__(self,item):
        print('您找的属性【%s】不存在'%item)

    def __setattr__(self,h,k):
        #print('执行setattr',h,k)
        if type(k) is str:            #要求字符串类型;
            print("开始设置")
            self.__dict__[h] = k.upper()        #写入字典并设置大写;
        else:
            print("必须是字符串类型")

    def __delattr__(self,item):
        print("不允许删除属性【%s】"%item)

f1 = Foo('xuan')
f1.age = '20'        #触发__setattr__
print(f1.__dict__)
print(f1.name)
print(f1.age)
print(f1.gender)
print(f1.slary)
del f1.name
print(f1.__dict__)

执行结果:

开始设置
开始设置
{'name': 'XUAN', 'age': '20'}
XUAN
20
您找的属性【gender】不存在
None
您找的属性【slary】不存在
None
不允许删除属性【name】
{'name': 'XUAN', 'age': '20'}

二次加工标准类型(包装)

包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知。

class List(list):
    def append(self,p_object):
        if type(p_object) is str:
            super().append(p_object)
        else:
            print("只能添加字符串类型")

    def show_midlle(self):
        mid_index = int(len(self)/2)
        return self[mid_index]

l1 = List('helloworld')
print(l1,type(l1))      #['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'] <class '__main__.List'>
print(l1.show_midlle()) # w
l1.append(11111111)     #只能添加字符串类型;
l1.append('2222222')    #['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '2222222']
print(l1)

授权

授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。实现授权的关键点就是覆盖__getattr__方法;

import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        self.file=open(filename,mode,encoding=encoding)
        self.mode=mode
        self.encoding=encoding

    def write(self,line):
        t=time.strftime('%Y-%m-%d %X')
        self.file.write('%s %s'%(t,line))

    def __getattr__(self,item):
        return getattr(self.file,item)

f1 = FileHandle('error.log','w+')
print(f1.file)  #<_io.TextIOWrapper name='error.log' mode='w+' encoding='utf-8'>
print(f1.__dict__)  #{'file': <_io.TextIOWrapper name='error.log' mode='w+' encoding='utf-8'>, 'mode': 'w+', 'encoding': 'utf-8'}
print('======>>',f1.read)   #======>> <built-in method read of _io.TextIOWrapper object at 0x03283030>
f1.write('hello world!\n')
f1.write('CPU温度过高\n')
f1.write('内存不足\n')
f1.write('磁盘空间不足\n')

isinstance和issubclass方法

class Foo:
    pass

class Bar(Foo):
    pass

b1 = Bar()
print(isinstance(b1,Bar))
print(isinstance(b1,Foo))
print(type(b1))

print(issubclass(Bar,Foo))      #判断Bar是否是Foo的子类;
print(issubclass(Foo,Bar))      #判断Foo是否是Bar的子类;

执行结果:

True
True
<class '__main__.Bar'>
True
False

item方法

class Foo:
    def __getitem__(self,item):
        print('getitem',item)
        return self.__dict__[item]
    def __setitem__(self,key,value):
        print('setitem')
        self.__dict__[key] = value
    def __delitem__(self,key):
        print('delitem')
        self.__dict__.pop(key)

f1 = Foo()
print(f1.__dict__)      #{}
f1['name'] = 'xuan'     #setitem
f1['age'] = 20          #setitem
print(f1.__dict__)      #{'name': 'xuan', 'age': 20}

del f1['age']           #delitem
print(f1.__dict__)      #{'name': 'xuan'}

print(f1['name'])       #getitem name  xuan

改变对象的字符串显示

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '名字是%s 年龄是%s'%(self.name,self.age)
f1 = Foo('xuan',20)
print(f1)           #名字是xuan 年龄是20

x = str(f1)
print(x)            #名字是xuan 年龄是20

y = f1.__str__()
print(y)            #名字是xuan 年龄是20
class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # def __str__(self):        #有str会直接执行str方法;
    #     return '这是str'
    def __repr__(self):
        return '名字是%s 年龄是%s'%(self.name,self.age)
f1 = Foo('xuan',20)
# print(f1)           #这是str
print(f1)           #名字是xuan 年龄是20

参考:https://www.cnblogs.com/linhaifeng/articles/6204014.html#_label3

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值