Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究

Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究,第1张

概述Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射: ? 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩 Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究 一丶反射 什么是反射:

? 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在lisp和面向对象方面取得了成绩。

Python面向对象的反射:

? 通过字符串的形式 *** 作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

####  四个实现反射的函数    # hasattr(),getattr(),setattr(),delattr()    ####  反射 整合版class Foo:    public_attr='静态属性'    def __init__(self,name,age):        self.name=name        self.age=age    def func(self):        print('Hello Python')obj=Foo('张三',18)        # 实例化对象##  检测是否含有XX属性print(hasattr(obj,'public_attr'))   #当前实例对象,是否含有静态变量public_attrprint(hasattr(obj,'func'))          #当前实例对象,是否含有func方法##  获取属性 getattr(对象,字符串,None)print(getattr(obj,'public_attr'),None)   #静态属性,不存在就返回Noneprint(getattr(obj,'func'))  # <bound method Foo.func of <__main__.Foo object at 0x0000015FF30EC8D0>>## 设置属性 setattr(对象,值)setattr(obj,'sex','男')  # 设置对象属性print(obj.__dict__) # {'name': '张三','age': 18,'sex': '男'}## 设置匿名方法 self为参数setattr(obj,'show_name',lambda self:self.name)print(obj.show_name(obj))   # 设置方法,print(obj.__dict__)# { 'show_name': <function <lambda> at 0x0000018512932EA0>}## 删除属性delattr(obj,'name')delattr(obj,'name')    # 不存在就报错print(obj.__dict__) # {'age': 18,'sex': '男','show_name': <function <lambda> at 0x000001D901BE2EA0>}
###  从当前 脚本(本类) 研究反射class B:    sta_='abc'def func1():    print('in func1')import systhis_module=sys.modules[__name__]  # 获取py文件对象print(this_module) # 这是一个对象  <module '__main__' from 'E:/file/oldboy学习笔记/Python之路/day26/01 反射.py'>print(hasattr(this_module,'func1')) # 判断函数名属性 存在不存在,Trueprint(getattr(this_module,'func1')) # 获得函数名属性  <function func1 at 0x00000225EBA92EA0>getattr(this_module,'func1')()   #获得函数名属性+()执行func1函数print(hasattr(this_module,'B')) # 判断类名属性 存在不存在 Trueprint(getattr(this_module,'B')) # 获得类名属性打印 <class '__main__.B'>cls=getattr(this_module,'B')    # cls 得到是一个B类的地址print(cls)                      # <class '__main__.B'>obj=cls()                       # cls+() 实例化一个对象print(obj.sta_)                 #  obj对象.B对象中的静态属性

? 案例:

class Auth:    funcli=[('login','请登录'),('register','请注册'),('exit','退出')]    def login(self):        print('登录函数')    def register(self):        print('注册函数')    def exit(self):        print('退出...')while 1:    obj=Auth()    for num,option in enumerate(obj.funcli,1):        print(num,option[0],option[1])    func_name = input('请输入选择:').strip()    if hasattr(obj,obj.funcli[int(func_name)-1][0]):        getattr(obj,obj.funcli[int(func_name)-1][0],'不存在')()
二丶函数vs方法 函数和方法有什么区别和相同之处?

? 函数是显性传参,方法是隐性传参

####  通过打印函数名确定    def func():        pass    print(func)  # 函数  <function func at 0x00000260A2E690D0>    class A:        def func(self):            pass    print(A.func)  # 函数 <function A.func at 0x0000026E65AE9C80>    obj = A()    print(obj.func)  # 方法 <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>####  通过types模块验证    from types import FunctionType  # 函数    from types import MethodType    # 方法     def func():        pass    class A:        def func(self):            pass    obj = A()    ## isinstance(obj,M) 判断 obj对象,是不是由M类 或 M类的派生类 实例化的对象    print(isinstance(func,FunctionType))         # True  函数    print(isinstance(A.func,FunctionType))       # True   类调用类中的func 是函数                print(isinstance(obj.func,FunctionType))     # False   实例对象调用 不是函数      print(isinstance(obj.func,MethodType))       # True    实例对象调用 是方法
研究类中的三个特殊的方法(静态方法,类方法,属性)
####  类中的静态方法是函数(静态函数)    from types import FunctionType    from types import MethodType    class A:        def func(self):            pass        @classmethod        def func1(self):            pass        @staticmethod        def func2(self):            pass    obj = A()    # 静态方法其实是函数    print(isinstance(A.func2,FunctionType))  # True    print(isinstance(obj.func2,FunctionType))  # True      ####  类中的类方法是方法(类方法)    from types import FunctionType    from types import MethodType    class A:                @classmethod        def paas(cls):            pass                @property        def a(self):            pass    obj=A()    #   类方法 类和对象 调用  都是方法    print(isinstance(obj.paas,FunctionType))    # False    print(isinstance(obj.paas,MethodType))      # True    print(isinstance(A.paas,FunctionType))      # False    print(isinstance(A.paas,MethodType))        # True     ####  类中的属性伪装函数 .  什么也不是,单纯的伪装属性    from types import FunctionType    from types import MethodType    class A:                @classmethod        def paas(cls):      # 类方法是 cls,实例对象或类调用.默认将从属的类地址传给cls (隐性传参)            pass                @property        def a(self):            pass            obj=A()     # 实例化对象    # 属性,类和对象 调用 什么都不是    print(isinstance(obj.a,FunctionType))    # False    print(isinstance(obj.a,MethodType))      # False    print(isinstance(A.a,FunctionType))      # False    print(isinstance(A.a,MethodType))        # False        ## 总结:    #1.类名 或 实例对象 调用类方法 都是 方法 method    #2.类名 或 实例对象 调用静态方法 都是 函数 function    #3.类名 或 实例对象 调用伪装属性函数. 什么都不是,单纯属性  ## 函数 和方法的本质区别:    ## 函数是显性传参,方法是隐性传参
三丶特殊的双下方法 定义:

? __方法名__的具有特殊意义的方法,不同的双下方法有不同的触发方式,开发中尽量不要使用双下方法

__len__ 一个对象可以使用len()函数,根本原因是这个对象从属的类有__len__方法
class A:    def __init__(self,sex,age):        self.name=name        self.sex=sex        self.age=age    def __len__(self):  # 必须有返回值,如果没有会报错(TypeError: 'nonetype' object cannot be interpreted as an integer)        print('触发了__len__')        return len(self.__dict__)       # 返回当前实例对象具有几个属性obj=A('张三','男',10)print(len(obj))   # 从属的类中没有__len__方法就报错 TypeError: object of type 'A' has no len()
__hash__对象使用hash()函数,调用当前本类__hash__方法,本类没有就从父类找__hash__
class A:    def __init__(self):        self.a=1        self.b=2    # 重写父类的__hash__方法    def __hash__(self): #需要返回值,没有返回值 报错:TypeError: __hash__ method should return an integer        return hash(str(self.a)+str(self.b))a=A()print(hash(a))  # 主动触发 __hash__方法,当前类如果没有__hash__ 就从父类找
__str____repr__
###  这俩方法的返回值必须是字符串,否则抛出异常###  str函数或者print函数--->obj.__str__()###  repr或者交互式解释器--->obj.__repr__()###  如果__str__没有被定义,那么就会使用__repr__来代替输出format_dict={    'nat':'{obj.name}-{obj.age}-{obj.sex}',#学校名-学校地址-学校类型    'tna':'{obj.sex}:{obj.name}:{obj.age}',#学校类型:学校名:学校地址    'tan':'{obj.sex}/{obj.age}/{obj.name}',#学校类型/学校地址/学校名}class School:    def __init__(self,age):        self.name=name        self.age=age        self.sex=sex    def __repr__(self):        return f'__repr__  {self.name} {self.age}'    def __str__(self):        return f'__str__ {self.name}{self.age}'    def __format__(self,format_spec):        if not format_spec or format_spec not in format_dict:            format_spec = 'nat'        fmt = format_dict[format_spec]        return fmt.format(obj=self)s1=School('ABC','123')print(repr(s1))  #  现在本类本类找__repr__ 如果没有 .  直接去父类找,返回一个对象地址print(str(s1))  #  会触发__str__,先在本类找__str__ 如果没有,找__repr__ .如果还没有去object类找,返回的是一个对象地址print('%s'%obj)     # %s 调用__str__print('%r'%obj)     # %r 调用 __repr__print(s1)   ###  __str__的优先级高于__repr__### 现在一般不再使用format()函数print(format(s1,'nat'))          # ABC-123-男print(format(s1,'tna'))          # 男:ABC:123print(format(s1,'tan'))          # 男/123/ABCprint(format(s1,'asfdasdffd'))   # ABC-123-男
__call__
class A:    def __init__(self):        self.a=1        print(111)    def __call__(self,*args,**kwargs):    # 不需要返回值,如果当前不存__call__在报错: TypeError: 'A' object is not callable        print(666)obj1=A()obj1()      # 实例对象+() 调用__call__方法
__eq__
class A:    def __init__(self):        self.a=1        self.b=2    def __eq__(self,other):    #  没有return 默认返回None        if self.a==other.a and self.b==other.b: # 条件不成立时,也返回None            return Truea=A()b=A()print(a==b)     # 调用__eq__方法### 面试题:###  set方法依赖集合中元素对象的__hash__ __eq__class Person:    def __init__(self,age,sex):        self.name = name        self.age = age        self.sex = sex    def __hash__(self):       # TypeError: unhashable type: 'Person'        # print('调用了1')        return hash(self.name+self.sex)    def __eq__(self,other):      #  判断当前对象是否 和其他对象的某些属性相同  other 接收set集合每次迭代的对象        # print('调用了')        # 解读 : 第一次实例化对象,self.name是列表中第一个对象执行__init__封装了        if self.name == other.name and self.sex == other.sex:return Truep_lst = []for i in range(84):    p_lst.append(Person('egon',i,'male'))   # 存放实例化对象print(p_lst)print(set(p_lst))       #  必须调用 __hash__,如果有__eq__ 就调用,没有就不调用.  迭代去重. so 第一次的时候 name 的值为列表第一个元素执行__init__封装的属性# print(dir(set))
__del__析构方法,当对象在内存中被释放时,自动触发执行。

? 此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:    def __del__(self):        print('执行我啦')f1=Foo()del f1print('------->')
__new__
class A:    def __init__(self,name):        self.name=name        print('in the __init__')    def __new__(cls,**kwargs):      # cls 自动接收 类名地址        print('in the __new__')        result=object.__new__(A)#由于重写了父类的__new__,需要调用父类的__new__方法才能创造对象空间        print(result)           # 生成对象空间的内存地址        return result           # 必须返回这个对象空间地址返回,才能执行__init__为对象封装属性    ####  类名()  先触发__new__ 并且将类名自动传递给clsobj=A('ale')        # 先执行__new__方法,如果没有执行父类的__new__.                      # 只有返回对象空间,才继续执行__init__方法,如果没有返回对象空间,对象为Noneprint(obj.name)print(obj)          #  __new__ 没有返回对象内存空间  对象=None
单例模式 : 节省内存
class F:    __instance=None    def __init__(self):        print('执行了init方法')    def __new__(cls,**kwargs):        if not cls.__instance:            object1=object.__new__(cls)            cls.__instance=object1        return cls.__instanceobj=F()obj1=F()obj2=F()print(obj,obj1,obj2)    # 三个内存地址都一样
__item__ * 对对象进行类似于字典的 *** 作*
### 类似于 @propertyclass Foo:    def __init__(self,name):        self.name = name    def __getitem__(self,item):  #        print('调用时执行 get')        print(self.__dict__[item])    def __setitem__(self,key,value):        print('设置时调用 set')        self.__dict__[key] = value    def __delitem__(self,key):        print('del obj[key]时,我执行')        self.__dict__.pop(key)    def __delattr__(self,item):        print('del obj.key时,我执行')        self.__dict__.pop(item)f1 = Foo('sb')f1['name']      # 调用时执行 __getitem__f1['age'] = 18  #设置新属性  __setitem__f1['age1'] = 19  # 设置新属性 __setitem__del f1.age1  # 删除属性 __delitem__del f1['age']  #删除属性 __delattr__f1['name'] = 'alex'  # 修改属性  __setitem__print(f1.__dict__)
__enter__ __exit__
## __enter__   __exit__# 如果想要对一个类的对象进行with  as 的 *** 作## 案例一:  with语句class A:    def __enter__(self):                            # 开启上下文管理器对象时触发此方法        print('before')    def __exit__(self,exc_type,exc_val,exc_tb):  # 执行完上下文管理器对象f1时触发此方法        print('after')with A() as a:    print('123')# before# 123# after          ## 案例二: with语句和initclass A:    def __init__(self):        print('init')    def __enter__(self):        print('before')    def __exit__(self,exc_tb):        print('after')with A() as a:    print('123')    # init 先执行                    ### 案例三:with和文件 *** 作class Myfile:    def __init__(self,path,mode='r',enCoding = 'utf-8'):        self.path = path        self.mode = mode        self.enCoding = enCoding    def __enter__(self):        print('进来了')        self.f = open(self.path,mode=self.mode,enCoding=self.enCoding)        return self.f    def __exit__(self,exc_tb):        print('关闭了')        self.f.close()with Myfile('file',mode='a') as f:    f.write('wahaha')    print('写完; ')            ### 案例四:  with和pickleimport  pickleclass MyPickledump:    def __init__(self,path):        self.path = path    def __enter__(self):        self.f = open(self.path,mode='ab')        return self    def dump(self,content):        pickle.dump(content,self.f)    def __exit__(self,exc_tb):        self.f.close()class Mypickleload:    def __init__(self,mode='rb')        return self    def __exit__(self,exc_tb):        self.f.close()    def load(self):         return pickle.load(self.f)    def loaditer(self):        while True:            try:                yIEld  self.load()            except EOFError:                break# with MyPickledump('file') as f:#      f.dump({1,2,3,4})with Mypickleload('file') as f:    for item in f.loaditer():        print(item)                        ### 案例五: with和pickle和iterimport  pickleclass MyPickledump:    def __init__(self,exc_tb):        self.f.close()    def __iter__(self):        while True:            try:                yIEld  pickle.load(self.f)            except EOFError:                break# with MyPickledump('file') as f:#      f.dump({1,4})with Mypickleload('file') as f:    for item in f:        print(item)
总结

以上是内存溢出为你收集整理的Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究全部内容,希望文章能够帮你解决Python进阶----反射(四个方法),函数vs方法(模块types 与 instance()方法校验 ),双下方法的研究所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1197975.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存