一、反射
1、反射是什么?
使用字符串数据类型的变量名来获取这个变量的值
2、常用几个场景?
input
根据用户的输入,获取相应的值
文件
从文件读出的字符串,想转成变量的名字
网络
将网络传输的字符串转成变量的名字
3、getattr 与 hasattr
getattr(变量名:命名空间,字符串:属于一个命名空间中的变量)
# 反射类中的静态属性,类方法,静态方法 class Foo: School = '希望小学' country = 'china' @classmethod def class_method(cls): print(cls.School) def static_method(): print('is static') while 1: inp = input('<<<').strip() print(getattr(Foo,inp))
# 反射对象中的变量,普通方法,对象属性 class Foo: def __init__(self,name,age): self.name = name self.age = age def eat(self): print('吃东西') f = Foo('xiaoming',12) print(getattr(f,'name')) print(getattr(f,'age')) getattr(f,'eat')()
# 反射本文件中的变量 a = 1 def fun(): print('xxx') class Foo:pass import sys # print(sys.modules['__main__']) #获取本文件的命名空间 F:/Demo/面向对象/反射与内置方法.py # print(sys.modules['__main__'].a) # print(__name__) print(getattr(sys.modules[__name__],'a')) print(getattr(sys.modules[__name__],'fun')()) obj = getattr(sys.modules[__name__],'Foo')() print(obj)
4、setattr 与 delattr
class Foo: country = 'china' def fun(): print('xxx') setattr(Foo,'country','us') #接收三个参数 命名空间 变量名 变量值 print(Foo.__dict__) print(getattr(Foo,'country')) print(Foo.country) setattr(Foo,'fun',fun) print(Foo.__dict__) getattr(Foo,'fun')() #一般不往空间中添加函数 delattr(Foo,'country') print(Foo.__dict__)
二、内置方法
1、不需要自己定义,本身就存在类中的方法
一般都是__变量名__,又叫双下方法,魔术方法
2、__str__ __repr__
class Course: def __init__(self,name,price,teacher): self.name = name self.price = price self.teacher = teacher def __str__(self): return 'str: %s %s %s' %(self.name,self.price,self.teacher) def __repr__(self): return 'repr: %s %s %s' % (self.name, self.price, self.teacher) course_list = [] python = Course('python',29800,'jing-l') linux = Course('linux',9800,'taix) course_list.append(python) course_list.append(linux) for id,course in enumerate(course_list,1): print(id,course) print('%s %s' %(id,course)) print(id,str(course)) print(id,repr(course)) print('%s %r' %(id,course)) # __str__ # 当你打印一个对象的时候 触发__str__ # 当你使用%s格式化的时候 触发__str__ # str强转数据类型的时候 触发__str__ # __repr__ # repr是str的备胎 # 有__str__的时候执行__str__,没有实现__str__的时候,执行__repr__ # repr(obj)内置函数对应的结果是 __repr__的返回值 # 当你使用%r格式化的时候 触发__repr__
3、__new__
# 在init之前实例化对象的第一步是__new__创建了一个空间 # 单例模式 class Foo: __instance = None def __init__(self,name): self.name = name def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = object.__new__(cls) return cls.__instance f1 = Foo('alex') f2 = Foo('zs')
4、__del__
class Foo: def __init__(self,name): self.name = name self.file = open('file.txt','w') def write(self): self.file.write('aaa') def __del__(self): # 析构方法 : 在删除这个类创建的对象的时候会先触发这个方法,再删除对象 # 做一些清理工作,比如说关闭文件,关闭网络的链接,数据库的链接 self.file.close() print('执行del了') f = Foo('zs') print(f)
5、__len__
class Foo: def __init__(self,name): self.name = name self.students = [] def __len__(self): return len(self.students) s1 = Foo('无极限') s1.students.append('zs') s1.students.append('lisi') s1.students.append('xm') print(len(s1))
6、__eq__
class Staff: def __init__(self,name,sex): self.name = name self.sex = sex def __eq__(self, other): # 原本是比较id内存地址 return self.__dict__ == other.__dict__ s1 = Staff('asf','male') s2 = Staff('asf','male') s3 = Staff('asf','fmale') print(s1 == s2) print(s3 == s2)
7、__hash__
set 的去重机制
1.对每一个元素进行hash计算出一个内存地址
2.到这个内存地址上查看
如果这块内存中没有值
将这个元素存到对应的内存地址上
如果这块内存中已经有值
判断这两个值是否相等
如果相等 就舍弃后面的值
如果不相等 就二次寻址再找一个新的空间来存储这个值
# 1.对于相同的值在一次程序的运行中是不会变化的 # 2.对于不同的值在一次程序的运行中总是不同的 class Staff: def __init__(self,name,age,sex,dep): self.name = name self.age = age self.sex = sex self.dep = dep def __hash__(self): return hash(self.name + self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True name_lst = ['yuan','egon','nazha','peiqi'] obj_lst = [] for i in range(100): name = name_lst[i%4] obj = Staff(name,i,'male','python') obj_lst.append(obj) print(len(obj_lst)) ret = set(obj_lst) print(ret) for i in ret: print(i.name,i.age)