python反射及内置函数方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python反射及内置函数方法相关的知识,希望对你有一定的参考价值。

isinstance(obj,cls)检查是否是obj或cls类的对象


1
class Foo: 2 pass 3 obj=Foo() 4 print(isinstance(obj,Foo)) 5 运行结果是True
检查sub类是否是super类的派生类
6 class Foo: 7 pass 8 class Bar(Foo): 9 pass 10 print(issubclass(Bar,Foo)) 11 运行结果是True

反射?

反射是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省)

python面向对象中的反射通过字符串形式操作对象相关的属性。反射共有四个函数加以使用:

hasattr,getattr,setattr,delattr

 1 class Test:
 2     ceshi="这是一个测试段"
 3     def test1(self):
 4         print("反射测试")
 5     def ceshi1(self):
 6         print("实例代码")
 7 print(hasattr(Test,"ceshi"))
 8 #setattr的使用示例
 9 print(Test.__dict__)
10 setattr(Test,"ceshi","修改内容")
11 setattr(Test,"ceshi2","添加内容")
12 print(Test.__dict__)
13 getattr的使用方式示例
14 print(getattr(Test,"ceshi"))
15 print(getattr(Test,"name","没有此项"))
16 #getattr可以通过字符串获取类字典内的值,在使用是可以传入三个参数,第三个参数为为获取到值后的返回值,可以自定义内容
17 delattr(Test,"ceshi")
18 print(Test.__dict__)
19 #delattr是删除类中的一个属性

反射的使用实例:

1.实现程序开发的可插拔。也就是可以先定义接口,然后补充接口功能,不影响程序的向下开发

示例:

公司需要开发一个FTP,开发人员一负责开发服务端,开发二负责开发客户端,当开发一没有定义下载的方法时,开发二可以使用已经定义好的方法名字,加判断,使用服务端方法,继续向下开发,不会影响程序的整体进度,当开发一重新对方法定义后,开发二不用做修改,可以直接使用服务端方法

#这是服务端
class Ftpserver:
    def __init__(self,addr):
        self.addr=addr
    def get(self):
        print("下载操作")
#这是客户端
from FTP import Ftpserver
f1=Ftpserver("192.168.1.100")
if hasattr(f1,"get"):
    func=getattr(f1,"get")
    func()
else:
    print("没有这个方法")

2.动态导入模块

 

__getattr__,__setattr__,__delattr__ 方法的解释使用

__getattr__(self,name):当属性name被访问且对象没有响应的属性时被自动调用

__setattr__(self,name,value):当试图给属性name赋值时会自动调用

__delattr__(self,name):当试图删除属性name时被自动调用

示例:

class Rectangle:
    def __init__(self):
        self.width=0
        self.height=0
    def __setattr__(self, name, value):#修改或者添加值的时候会触发setattr运行
        if name =="size":
            self.width,self.height=value
        else:
            self.__dict__[name]=value
    def __getattr__(self, name):#当调用的方法不存在时,运行getattr
        if name=="size":
            return self.width,self.height
        else:
            raise  AttributeError
r1=Rectangle()
r1.height=10
r1.width=100
#print(r1.__dict__)
print(r1.__setattr__("size1","10"))
r1.__dict__["lzh"]=28
print(r1.__dict__)
print(r1.rea)#调用不存在方法,触发__getattr__运行,报错

 

二次加工标准类型

基于继承的二次包装

python的标准类型提供了很多丰富的使用模式,但是有时候我们需要自己定制一些类型的使用,比如列表添加时限制添加值的类型等:

示例:

class List(list):#继承list类
    def append(self, object: int):
        if not isinstance(object,int):#定制数据类型,判断值
            raise TypeError#错误后自动报错
        super(List, self).append(object)#使用super调用基类
l=List([1,2,3,4])
l.append(1)
print(l)

基于授权的标准类定义

基于授权的类定义,可以添加新建删除原有类的方法,其他保持原样。实现授权的关键点在于使用__getattr__特殊方法的使用

示例:

class List:#新建一个新的类,不继承原list任何属性
    def __init__(self,seq):#建立一个绑定方法,设立初始值
        self.seq=seq
    def append(self,value):#定义一个append方法
        if isinstance(value,int):#判断类型
            self.seq.append(value)#self.seq的意义在于调用原list方法,授权
        else:
            raise TypeError
    def __getattr__(self, item):#此方法的使用是授权的重点,意义在于没有调用的属性时运行此处方法
        return getattr(self.seq,item)
    @property
    def mid(self):#定制一个取列表中间值的方法
        return self.seq[len(self.seq)//2],type(self.seq[len(self.seq)//2])
l1=List([1,2,3])
print(l1.__dict__)
print(getattr(l1,"seq"))
l1.append(11)
l1.append(12)
l1.append(0)
l1.pop(0)

 

 

基本的序列和映射规则

__getitem__ ,__setitem__,__delitem__

 

__getitem__(self,key):这个方法返回与所给键对应的值。

__setitem__(self,key,value):这个方法按一定的方式存储和key相关的value,该值可使用__getitem__获取。当然,只能为可以修改的对象定义这个方法。

__delitem__(self,key):这个方法在对一部分对象使用del语句时被调用,同时必须删除和键相关的键

 示例:

class test:
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item):
        return self.__dict__(item)
    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        self.__dict__.pop(key)
t1=test("lzh")
t1.__dict__["age"]=18
t1.age=20
print(t1.age)
print(t1.__dict__)

 __slost__方法的使用

__slost__方法的优点:1,节省内存空间

           2,可以在一定程度上限制数据属性的添加使用。

示例:

class Foo:
    __slots__ = ["z","x"]#在查看类的字典时,会是一个列表

f1=Foo()
f1.z=1#必须slost列表中定义的数据属性名称
f1.x=10
print(Foo.__dict__)
print(f1.z,f1.x)
#在使用__slost__时,没有对象字典,只有一个类的字典可以查到

__del__析构函数

import time
class Open:
    def __init__(self,filepath,m=r,encode=utf-8):
        self.f=open(filepath,mode=m,encoding=encode)
    def write(self,line):
        pass

    def __getattr__(self, item):
        return getattr(self.f,item)
    def __del__(self):#此处使用析构函数,触发一个删除操作,当函数需要删除值或者关闭一个文件时,都是在删除一个内存引用计数。
        print("——>del")
        self.f.close()
#
f=Open(b.txt,w)
f1=f#这时候有2个引用关系,所以del在删除时不会立即执行
del f#删除操作,删除引用计数,在程序运行完之前自己解除引用,当没有此操作时,程序会在运行结束后,由解释器内存回收机制直接回收
print(">>>>")

__next__,__iter__迭代器协议

示例:

#定义一个range方法,实现其功能
class rang:
    def __init__(self,start,stop):
        self.start=start
        self.stop=stop
    def __iter__(self):
        return self
    def __next__(self):
        if self.start==self.stop:
            raise StopIteration
        self.start+=1
        return self.start-1
r1=rang(1,10)
for i in r1:
    print(i)

 

__call__使用方法

对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为,如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2...) 等同于调用x.__call__(self, arg1, arg2) 。

 模拟函数的对象可以用于创建防函数(functor) 或代理(proxy)

1 class Foo:
2     def __init__(self,num):
3         self.num=num
4     def __call__(self, *args, **kwargs):#定义__call__函数方法
5         print(args,kwargs)
6 f1=Foo(100)
7 f1(120,130,a=10,y=200)#在调用时,不需要加括号调用。

 



以上是关于python反射及内置函数方法的主要内容,如果未能解决你的问题,请参考以下文章

绑定与非绑定方法及反射,isinstance和issubclass内置函数

Python学习第14篇:面向对象之反射以及内置方法

python学习8_1 面向对象(继承多态封装)以及零散概念(组合,property,绑定方法与非绑定方法,反射,内置函数)

面向对象之反射及内置方法

反射(高大上)类的内置方法

面向对象之反射及内置方法