python之魔法方法
is 和 == 的关系
''' == 值相等 值运算 is 内存地址相等 身份运算 is 要求更苛刻 不仅要求值相等,还要求内存地址相同 ''' a = 111 b = 111 a == b # 值相等 值运算使用 a is b # 值相等内存地址不相等使用
is 和 isinstance的关系
class A: pass class B(A): pass b = B() print(isinstance(b, B)) print(isinstance(b, A)) print(issubclass(B, A)) class Mystr(str):pass ms = Mystr('alex') print(ms) print(type(ms) is str) # 不包含继承关系,只管一层 print(isinstance('alex', str)) # 包含所有的继承关系
__call__方法 相当于 对象()
class A: def __call__(self, *args, **kwargs): print('执行call方法了') def call(self): print('执行call方法了') class B: def __init__(self,cls): print('在实例化A之前做一些事情') self.a = cls() self.a() print('在实例化A之后做一些事情') a = A() a() # 对象() == 相当于调用__call__方法 a.call() A()() # 类名()() ,相当于先实例化得到一个对象,再对对象(),==>和上面的结果一样,相当于调用__call__方法 B(A)
iter和next例子
# iter和next的例子 # __iter__ iter(obj) # __next__ next def iter(obj): return obj.__iter__() # 返回迭代对象 li = [1,2,3] print(iter(li))
__len__ len()
class Mylist: def __init__(self): self.li = [1,2,3] def __len__(self): print('len') # return len(self.li) return len(self.__dict__) # 有多少个属性 l = Mylist() print(len(l)) # len(obj)相当于调用了这个对象的__len__方法 # __len__方法return的值就是len函数的返回值 # 如果一个obj对象没有__len__方法,那么len函数会报错 # 练习 写一个类 统计str的长度 # self.s = '' len(obj) = str的长度 class StrLen: def __init__(self,s): self.s = s def __len__(self): return len(self.s) b = StrLen('adsgsdg') print(len(b))
__new__ # 构造方法 开劈内存空间的类的构造方法
__init__ # 初始化方法
class Single: def __new__(cls, *args, **kwargs): # 在实例化之后,__init__之前先执行new来创建一块空间 obj = object.__new__(cls) # Single的new,Single没有,只能调用object的new方法 print('new', obj) return obj def __init__(self): print('init', self) # 1、开辟一个空间,属于对象的 # 2、把对象的空间传给self,执行init # 3、将这个对象的空间返回给调用者
单例类
# 单例类 class single: __ISINSTANCE = None def __new__(cls, *args, **kwargs): if not cls.__ISINSTANCE: cls.__ISINSTANCE = object.__new__(cls) return cls.__ISINSTANCE def __init__(self,name,age): self.name = name self.age = age # 不论实例多少个对象结果都是同一个内存空间 a = single('alex',32) b = single('wang', 43) print(a.name) print(b.name)
__str__ 方法
class Student: def __str__(self): ''' :return: 返回自定义内容 ''' return f"{self.school} {self.class_name} {self.name} {self.age}" def __init__(self, school, class_name, name): self.school = school self.class_name = class_name self.name = name self.age = 20 name1 = Student('oldboy', 'py', 'alex') name2 = Student('oldboy', 'py', 'abc') print(name1) # 直接调用对象输出自定义内容,需要使用__str__方法 print(str(name1)) # 内置的数据类型,内置的类,相当于执行__str__ print('学生: %s' % name1) print(f'学生:{name1}') # print一个对象相当于调用一个对象的__str__方法 # str(obj),相当于执行obj.__str__方法 # '%s'%obj,相当于执行obj.__str__方法
__repr__
# %s 和 %r 的区别是 %r显示原字符 print("----%s----" % ('abc')) print("----%r----" % ('abc')) """
__str__ : str(obj) 要求必须实现了__str__,要求这个方法的返回值必须是字符串str类型
# print %s str
__repr__ 对应repr(obj) %r __repr__是__str__的备胎,当__str__存在时执行__str__返回值 ,__str__不存在时,那么print %s str都会执行__repr__,优先使用__repr__方法。
在子类中使用__str__,先找子类的__str__,没有则向上找,只要父类不是object,就执行父类的__str__。
但是如果除了object之外的父类都没有__str__方法,就执行子类的__repr__方法,如果子类也没有,向上继续找父类中的__repr__方法。如果都没有找到,再执行object类中的__str__方法。 """ class A: def __init__(self, name): self.name = name def __str__(self): return f"str {self.name}" def __repr__(self): return f"repr {self.name}" class B(A): # 优先执行子类方法 def __init__(self, name): self.name = name def __repr__(self): return '****' a = B('alex') print(a) print("%s | %r" % (a, a))
__del__ del()
# __del__方法 class File: def __init__(self, fname): self.f = open(fname) def read(self): print(self.f.read()) def __del__(self): # 在清除一个对象在内存中的使用的时候, 会触发这个对象所在的类中的析构方法 print('执行我了') self.f.close() f = File('chinese.txt') f.read()
item系列 []
# item系列 # 对象[] 就需要实现item系列 # getitem obj['wioe'] # setitem obj['uyr'] = jash # delitem del obj['asfjh'] # 使用反射 class A: def __getitem__(self, item): return getattr(self, item) def __setitem__(self, key, value): setattr(self, key, value) def __delitem__(self, key): delattr(self, key) a = A() a['s32'] = 'fdfd' print(a['s32']) del a['s32'] print(a['s32']) # 使用列表 class B: def __init__(self, li): self.li = li def __getitem__(self, item): return self.li[item] def __setitem__(self, key, value): self.li[key] = value def __delitem__(self, key): self.li.pop(key) b = B(['111', '222', '333', '444', 'ddd']) print(b[0]) b[2] = 'sss' print(b.li) del b[1] print(b.li)
__hash__ hash()
# __hash__方法 hash() # 在同一次执行中,相同的值hash值总是一样的 # set的去重 # 字典的快速查找 # hash(obj) #obj内部必须实现了__hash__方法 # 练习题 # 一个类 # 对象的属性 : 姓名 性别 年龄 部门 # 员工管理系统 # 内部转岗 python开发 - go开发 # 姓名 性别 年龄 新的部门 # alex None 83 python # alex None 85 luffy # 1000个员工 # 如果几个员工对象的姓名和性别相同,这是一个人 # 请对这1000个员工做去重 class Employee: def __init__(self, name, age, sex, partment): self.name = name self.age = age self.sex = sex self.partment = partment def __hash__(self): return hash('%s%s' % (self.name, self.sex)) def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True employ_lst = [] for i in range(200): employ_lst.append(Employee('alex', i, 'male', 'python')) for i in range(200): employ_lst.append(Employee('wusir', i, 'male', 'python')) for i in range(200): employ_lst.append(Employee('taibai', i, 'male', 'python')) # print(employ_lst) employ_set = set(employ_lst) for person in employ_set: print(person.__dict__) # set集合的去重机制 : 先调用hash,再调用eq,eq不是每次都触发,只有hash值相等的时候才会触发
__eq__ ==
# __eq__方法 # == # set的去重 class A: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name and self.age == other.age: return True a = A('alex', 83) aa = A('alex', 83) aa2 = A('alex', 83) aa3 = A('alex', 83) aa4 = A('alex', 83) aa5 = A('alex', 83) aa6 = A('alex', 83) print(a, aa) print(aa3 == aa == aa4) # ==这个语法 是完全和__eq__