1.反射
1.什么叫反射
反射就是通过字符串数据类型的变量名来访问变量的值
像x.y这样的形式,都可以用反射
# 例: print('aaa'.startswith) # <built-in method startswith of str object at 0x000001D949B6B500> ret = getattr('aaa', 'startswith') print(ret) # <built-in method startswith of str object at 0x000001D949B6B500> # 执行 print('aaa'.startswith('a')) # True print(ret('a')) # True
2.反射的类型
对象名 反射 对象属性 和 方法
类名 反射 静态属性
模块 反射 模块中的名字
反射 对自己所在文件中的名字
1) 对象名 反射 方法
# 对象名 反射 方法 class Person: def eat(self):print('eating') def drink(self):print('drinking') def play(self):print('playing') def sleep(self):print('sleepping') alex = Person() while True: inp = input('>>> ') # if hasattr(alex, inp): getattr(alex, inp)() # >>> eat # eating # >>> drink # drinking # >>> play # playing # >>> sleep # sleepping # >>> eatt # getattr(alex, inp)() # AttributeError: 'Person' object has no attribute 'eatt'
说明
1. 首先 使用getattr取获取一个名字,如果在这个对象的命名空间中没有这个名字,会报错 2. 这时候就引入了getattr的反射好伴侣hasattr 3. 如果使用getattr去获取一个方法,那么只能拿到这个方法的内存地址 4. 加上括号就是执行,当然,括号里的参数可以照传不误 5. 如果获取getattr获取一个属性,那么直接使用反射就可以获取到值
引入hasattr,判断对象是否含有这个方法
# 引入了getattr的反射好伴侣hasattr,判断对象是否含有这个方法 class Person: def eat(self):print('eating') def drink(self):print('drinking') def play(self):print('playing') def sleep(self):print('sleepping') alex = Person() while True: inp = input('>>> ') if hasattr(alex, inp): getattr(alex, inp)() # >>> eat # eating # >>> eatt
2) 对象名 反射 对象属性
class Person: def __init__(self,name): self.name = name def eat(self):print('eating') def drink(self):print('drinking') def play(self):print('playing') def sleep(self):print('sleepping') alex = Person('alex') print(getattr(alex, 'name')) # alex
3) 类名 反射 静态属性
class Person: role = '静态属性' print(getattr(Person, 'role')) # 静态属性
4) 模块 反射 模块中的名字
''' mo.py文件 money = 100 def func1(): print('in func1') class Manager: def eat(self): print('eating') ''' import mo import time print(mo.money) # 100 # 反射模块中的变量 print(getattr(mo, 'money')) # 100 mo.func1() # in func1 # 括号内接参数 getattr(time, 'sleep')(0.5) # 反射模块中的函数名 getattr(mo, 'func1')() # in func1 # 反射模块中的类名 Manager = getattr(mo, 'Manager') print(Manager) # <class 'mo.Manager'> a = Manager() a.eat() # eating
5) 反射自己所在文件中的名字
# 思路:找自己的文件名 value = '123' import sys print(sys.modules['__main__']) print(getattr(sys.modules['__main__'], 'value'))
2.isinstance和issubclass
# isinstance() class Foo: pass obj = Foo() print(isinstance(obj, Foo)) # True # 说明:isinstance(obj, cls) 检查obj是否是类的对象 # issubclass() class Foo: pass class Son(Foo): pass print(issubclass(Son, Foo)) # True # 说明:issubclass(Son, Foo) 检查Son类是否是Foo类的子类
3.__new__
# __new__ 构造方法、创建一个对象 # __init__ 初始化方法 class Foo: def __new__(cls, *args, **kwargs): #self还没有创建 print('执行我啦') return object.__new__(cls) #-->self def __init__(self): print('2222222') Foo() # 执行我啦 # 2222222 # 说明:先执行new方法,object.__new__ # 再执行__init__ # # # Foo() --> python解释器接收到你的python代码 # python解释器替你去做了很多操作 # 包括 主动帮助你 调用 new方法 去创造一个对象 -- 开辟内存空间 -- python语言封装了开辟内存的工作 # object的new方法里 -- 帮你创造了对象 # 调用init的用到的self参数,就是new帮你创造的对象
单例模式
# 什么叫单例模式 # 单例模式 : 某一类 只有一个实例 class Person: __isinstance = None def __new__(cls, *args, **kwargs): if not cls.__isinstance : obj = object.__new__(cls) cls.__isinstance = obj return cls.__isinstance def __init__(self,name): self.name = name alex = Person('alex') alex.age = 18 egon = Person('egon') print(egon.age) # 18 print(id(alex)) # 2550191724752 print(id(egon)) # 2550191724752 print(alex.name) # egon print(egon.name) # egon # __new__生孩子 # 类 : 生一个小孩__new__ 给这个小孩穿衣服 __init__ # 单例模式下的类 : 只有一个小孩,只有内部的属性变了,孩子没变
4.__len__
class A: def __len__(self): return 10 a = A() print(len(a)) # 10 class A: pass a = A() print(len(a)) # print(len(a)) # TypeError: object of type 'A' has no len()
5.__str__和__repr__
format_dict={ 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 } class School: def __init__(self,name,addr,type): self.name=name self.addr=addr self.type=type def __repr__(self): return 'School(%s,%s)' %(self.name,self.addr) # def __str__(self): # return '(%s,%s)' %(self.name,self.addr) def __format__(self, format_spec): # if 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) # 1- 改变对象的字符串显示__str__,__repr__ s1=School('oldboy1','北京','私立') print('from repr: ',repr(s1)) # from repr: School(oldboy1,北京) print('from str: ',str(s1)) # from str: (oldboy1,北京) print(s1) # (oldboy1,北京) # 将__str__注释后的结果为__repr__的格式化结果 # School(oldboy1,北京) # 说明:str函数或者print函数--->obj.__str__() # repr或者交互式解释器--->obj.__repr__() # 如果__str__没有被定义,那么就会使用__repr__来代替输出 # 注意:这俩方法的返回值必须是字符串,否则抛出异常 # 2- format自定义格式化字符串 print(format(s1,'nat')) # oldboy1-北京-私立 print(format(s1,'tna')) # 私立:oldboy1:北京 print(format(s1,'tan')) # 私立/北京/oldboy1 print(format(s1,'asfdasdffd')) # oldboy1-北京-私立
%s和%r
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b = B() print('%s' % b) # str : class B print('%r' % b) # repr : class B
6.其他方法
class Person: def __init__(self,name): self.name = name def __str__(self): return 'a object of Person named %s'%self.name def __hash__(self): return 1231212 def __len__(self): return 10 a = Person('alex') b = Person('egon') # print(len(a)) # print(hash(a)) print(a) # a object of Person named alex print(b) # a object of Person named egon print(len(a)) # 10 print(hash(a)) # 1231212 print(len(b)) # 10 print(hash(b)) # 1231212
# 说明:类中的内置方法很多都和内置函数相关