一、上下文管理器
python的上下文管理协议:包含__enter__() 、__exit__()方法
上下文管理器:支持"上下文管理协议"的对象
with 语句操作上下文管理器对象:
with object as o: pass
其中:
-
with后的object是上下文管理器的对象;o是__enter__()的返回值
-
在执行with里的语句之前,先执行__enter__(),再执行with中的语句,最后执行__exit__()
# 自定义上下文管理器 class MyClass(object): def __enter__(self): print("enter is running...") def __exit__(self, exc_type, exc_val, exc_tb): print("exit is running...") def main(): # 实例对象 obj = MyClass() with obj as o: print("with is running...") if __name__ == '__main__': main() """ enter is running... with is running... exit is running... """
常见的上下文管理器:
with open("text.txt","w",encoding="utf8") as f: f.write("hello world")
open能够被with操作:
f = open("上下文管理器.txt") print(dir(f)) """ ... ,'__enter__', '__eq__', '__exit__', ... """ # open()的返回值f是一个上下文管理器,所以可以被with操作
注意:不是上下文管理器,不能被with操作
with 1 as o: print("hello") """ with 1 as o: AttributeError: __enter__ """
一个对象不是上下文管理器,怎么变成上下文管理器?
在继承的新的类中,添加__enter__() 、__exit__()方法
class Base(object): pass class MyBase(Base): def __enter__(self): pass def __exit__(self, exc_type, exc_val, exc_tb): pass def main(): obj = MyBase() with obj as o: print('with is running....') if __name__=="__main__": main()
二、魔术方法
在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”(魔术方法)
参考转载自:https://www.cnblogs.com/nmb-musen/
参考转载自:https://www.cnblogs.com/pyxiaomangshe/p/7927540.html
1)__str__
当使用print输出对象的时候,只要自己定义了__str__(self)
方法,那么就会打印这个方法中return的数据
__str__
方法需要返回一个字符串
不写__str__()方法,默认继承object的str方法,返回的是存储地址
class MyClass(object): def __init__(self,name): self.name = name def main(): a = MyClass("zjx") print(a) if __name__ == '__main__': main() # <__main__.MyClass object at 0x000001B57D0BEC88>
重写__str__()
class MyClass(object): def __init__(self,name): self.name = name def __str__(self): print("__str__ is running...") return self.name def main(): obj = MyClass("zjx") print(obj) if __name__ == '__main__': main() """ __str__ is running... zjx """
2.__add__
自定义的类生成的对象(实例)能够使用运算符操作
def main(): a = [1, 2] b = [3, 4] return a + b if __name__ == '__main__': print(main()) # [1, 2, 3, 4]
思考:为什么list能够相加?因为list含有__add__属性
def main(): a = [1, 2] b = [3, 4] print(hasattr(a,"__add__")) # True return a + b if __name__ == '__main__': print(main())
对象没有__add__属性,进行相加会报错
class MyClass(object): pass def main(): obj1= MyClass() obj2 = MyClass() return obj1 + obj2 if __name__ == '__main__': print(main()) ''' TypeError: unsupported operand type(s) for +: 'MyClass' and 'MyClass' '''
对象添加__add__属性;
class MyClass(object): def __init__(self, value): self.value = value def __add__(self, other): return self.value + other.value def main(): obj1 = MyClass(1) obj2 = MyClass(2) return obj1 + obj2 if __name__ == '__main__': print(main()) # 3
# obj1是self obj2是other
3.__del__
python解释器自动删除对象,释放内存
class MyClass(object): def __init__(self): print("init is running...") def __new__(cls, *args, **kwargs): print("new is running...") instance = super().__new__(cls) return instance def __del__(self): print("del is running...") def main(): obj1 = MyClass() obj2 = MyClass() if __name__ == '__main__': main() print("main() is running...") """ new is running... init is running... new is running... init is running... del is running... del is running... main() is running... """
del关键字手动删除
class MyClass(object): def __init__(self):
# 构造 初始化 print("init is running...") def __new__(cls, *args, **kwargs):
# 创建对象、分配内存 print("new is running...") instance = super().__new__(cls) return instance
def __del__(self):
# 销毁对象 java里叫‘’析构 print("del is running...") def main(): obj1 = MyClass() obj2 = MyClass() del obj1 del obj2
4.多态
面向对象的三大特征:封装、继承、多态
多态就是在子类中重写父类的方法,作用是同样名称的方法在不同的子类中会有不同的行为。
class MyClass(object): def music(self): print("myclsss music is running...") class AClass(MyClass): def music(self): print("Aclass music is running...") class BClass(MyClass): def music(self): print("Bclass music is running...") def func(obj): obj.music() # 只要这个对象有music方法,就会正常调用 if __name__ == '__main__': m = MyClass() a = AClass() b = BClass() #上面三个对象都有music方法,都可以正常调用该方法 func(a) func(b) func(m) """ Aclass music is running... Bclass music is running... myclsss music is running... """
5.鸭子类型
python不支持多态也用不到多态,多态的概念是应用于java和C#这一类强类型语言中,而Python崇尚鸭子类型(Duck Typing)
一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
不管什么类型,只要有核心的功能。就可以是鸭子类型
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。
class Animal(object): def run(self): print("animal is running...") class Cat(Animal): def run(self): print("cat is running...") class Dog(Animal): def run(self): print("dog is running...") class Person(object): def run(self): print("person is running...") def canrun(obj): # 只要obj含有run()方法,就是个鸭子类型 obj.run() if __name__ == '__main__': canrun(Animal()) canrun(Cat()) canrun(Person()) """ animal is running... cat is running... person is running... """
6.类方法的使用
类方法是为了创建对象
# 类方法创建对象 class Person(object): def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name @classmethod def teacher(cls,full_name): # 类方法,扩展一个创建对象的方式 first_name, last_name = map(str, full_name.split(" ")) obj = cls(first_name, last_name) return obj if __name__ == '__main__': # 普通方式创建对象 zhangsan = Person("san", "zhang") print(zhangsan.first_name) # 类方法创建对象 使用类方法后,多了一种创建对象的方法 teacher = Person.teacher("si li") print(teacher.first_name) print(teacher.last_name)
7.__getitem_
有__getitem__方法的对象才能用[ ]操作
在类中定义了这个__getitem__ 方法,那么它的实例对象obj,可以obj[key] 取值,当实例对象做obj[key] 运算时,会调用类中的方法__getitem__
class MyClass(object): def __init__(self): self.items = [1, 2, 3] def __getitem__(self, item): return self.items[item] if __name__ == '__main__': myclass = MyClass() print(myclass[0]) # 1 print(myclass[1]) # 2 print(hasattr(myclass, "__getitem__")) # True print(hasattr(list, "__getitem__")) # True print(hasattr(tuple, "__getitem__")) # True
8.__getattr__
__getattr__方法,对象没有该属性而调用该属性时,会报系统内置的属性错误信息
class Myclass(object): def __init__(self,name): self.name = name if __name__ == '__main__': A = Myclass("zhangsan") print(A.value) # AttributeError: 'Myclass' object has no attribute 'value'
添加__getattr__方法,执行调用对象的属性,而对象无此属性时,会调用__getattr__方法
class Myclass(object): def __init__(self,name): self.name = name def __getattr__(self, item): return 1 if __name__ == '__main__': A = Myclass("zhangsan") print(A.value) # 1 对象A并没有value属性,但是输出的是__getattr__的返回值
重写__getattr__方法,自定义报错信息
class MyAttributionError(Exception): def __init__(self,msg = "属性不存在"): super().__init__(self) self.msg = msg def __str__(self): return self.msg class Myclass(object): def __init__(self,name): self.name = name def __getattr__(self, item): raise MyAttributionError if __name__ == '__main__': A = Myclass("zhangsan") print(A.value) """ raise MyAttributionError __main__.MyAttributionError: 属性不存在 """