面向对象的反射和双下方法
1.函数vs方法
-
函数:全部都是显性传参
-
方法:存在隐性传参
-
判断方法
-
通过函数名可大致判断
-
通过types模块去验证
-
from types import FunctionType from types import MethodType def func(): pass class A: def func(self): pass @staticmethod def f(): pass # print(isinstance(func, FunctionType)) # print(isinstance(func, MethodType)) # 类名调用func 就是一个函数 # print(isinstance(A.func, FunctionType)) # print(isinstance(A.func, MethodType)) # obj = A() # 对象调用func 就是一个方法 # print(isinstance(obj.func, FunctionType)) # print(isinstance(obj.func, MethodType)) # 对于静态方法的研究 # print(isinstance(A.f, FunctionType)) # print(isinstance(A.f, MethodType)) # obj = A() # # 对象调用func # print(isinstance(obj.f, FunctionType)) # print(isinstance(obj.f, MethodType))
-
2.反射
-
概念:主要是指程序员可以访问,检测和修改它本身状态或行为的一种能力(自省),
-
python中面向对象的反射 : 通过字符串的形式操作对象的相关属性,python中的一切事物都是对象(都可以使用反射)
-
['从实例的角度去研究反射']
-
# class A: # # static_field = '静态属性' # # def __init__(self,name,age): # self.name = name # self.age = age # # def func(self): # print('in A func') # obj = A('MC骚Q',18) # print(obj.name) # print(hasattr(obj,'name')) #检查是否有'name'属性 # print(getattr(obj,'name1','没有该属性')) #获取属性,如果没有设置第三个元素,查询不到就会报错 # print(getattr(obj,'name')) # print(getattr(obj,'name1')) #报错 # # setattr(obj,'hobby','玩') #增加新的属性 # print(getattr(obj,'hobby')) # # delattr(obj,'name') #删除该属性 # print(hasattr(obj,'name')) # if hasattr(obj,'static_field'): # print(getattr(obj,'static_field')) # # if hasattr(obj,'func'): # getattr(obj,'func')()#不用实例化,可直接调用方法
-
从类的角度研究反射
-
# class A: # # static_field = '静态属性' # # def __init__(self,name,age): # self.name = name # self.age = age # # def func(self): # print('in A func') # obj = A('大表哥',18) # print(getattr(A,'func')) # getattr(A,'func')(obj)
-
从脚本的角度研究反射
-
# import sys # def func1(): # print('in func1') # this_modules = sys.modules[__name__] #获取当前脚本这个对象 # print(this_modules) # print(getattr(this_modules,'func1')) # getattr(this_modules,'func1')() # class B: # static = "B类" # import sys # this_modules = sys.modules[__name__] # cls = getattr(this_modules,"B") # obj = cls() # print(obj.static)
-
应用场景
-
'选择界面' # class Auth: # # def login(self): # print('登陆函数') # # def register(self): # print('注册函数') # # def exit(self): # print("退出") # # while 1: # function_list = [('login','登录'),('register','注册'),("exit",'退出')] # for num,option in enumerate(function_list,1): # print(num,option[1]) # func_name = input("群输入选择:").strip() # obj = Auth() # if hasattr(obj,func_name): # getattr(obj,func_name)() # else: # print('输入错误')
-
3.双下方法
-
双下方法是特殊方法,主要供python源码程序员使用
-
__len__
-
# class A: # def __init__(self,name): # self.name =name # # def __len__(self): # print('触发__len__方法') # return 10 # # obj = A('MC') # ret = len(obj) # print(ret)
-
-
__hash__
-
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
-
-
__str__
-
# class A: # # def __init__(self): # self.name = '太白' # # def __str__(self): # return self.name # # obj = A() # print(obj) # print(str(obj))
-
-
__repr__
-
# class Student: # def __init__(self,name,age,sex): # self.name = name # self.age =age # self.sex = sex # # def __repr__(self): # return "12" # # def __str__(self): # return f"{self.sex}123" # # object = Student(1,2,3) # object1 = Student(1,2,4) # object2 = Student(1,2,5) # # print(str(object)) #会触发__str__ # print(object) # print(object1) # print(object2) # print(f"此对象为%s" %object) #格式化输出会触发__str__ # print(f"此对象为%r" %object) #格式化输出会触发__repr__ # # print(obj) #同时存在__str__和__repr__会优先选择__str__执行,优先级别高
-
-
__call__
-
# class A: # def __init__(self): # self.a =1 # print(111) # # def __call__(self, *args, **kwargs): # print(666) # # obj = A() # obj()
-
-
__eq__
-
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
-
-
__del__
- 析构方法,当对象在内存中被释放时,自动触发执行
- 此方法一般无需定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因此此工作都是交给python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发和执行的.
-
__new__
-
# class A(object): # # def __init__(self): # print('in __init__') # # def __new__(cls, *args, **kwargs): # print(cls) #A # print('in __new__') # object1 = object.__new__(cls) #2. 其次利用object类的__new__产生一个对象空间 # return object # #3. 将这个对象空间返回给了A()即obj # # obj = A()#1. 先触发__new__,将类名自动传给cls
-
-
__item__
-
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): 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['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
-
-
上下文管理器相关__enter__和__exit__
-
# 如果想要对一个类的对象进行with as 的操作 不行。 class A: def __init__(self, text): self.text = text with A('大爷') as f1: print(f1.text)
-
class A: def __init__(self, text): self.text = text def __enter__(self): # 开启上下文管理器对象时触发此方法 self.text = self.text + '您来啦' return self # 将实例化的对象返回f1 def __exit__(self, exc_type, exc_val, exc_tb): # 执行完上下文管理器对象f1时触发此方法 self.text = self.text + '这就走啦' with A('大爷') as f1: print(f1.text) print(f1.text)
-
自定义上下文管理器
-
class Diycontextor: def __init__(self,name,mode): self.name = name self.mode = mode def __enter__(self): print "Hi enter here!!" self.filehander = open(self.name,self.mode) return self.filehander def __exit__(self,*para): print "Hi exit here" self.filehander.close() with Diycontextor('py_ana.py','r') as f: for i in f: print i
-