面向对象高级编程
1.使用__slots__:主要是节省内存,其次可以限制定义 我们可以给一个实例绑定一个属性: 直接写:实例名.属性名 = 数据 ,给实例绑定的属性只能在该实例中使用 我们也可以给实例添加一个方法: 例: >>> class Student(): """定义一个学生的类""" def __init__(self,name,age): self.name = name self.age = age >>> from types import MethodType # 导入模块 >>> s = Student('Bob',18) >>> s.name 'Bob' >>> s.age 18 >>> # 定义一个函数作为实例方法 >>> def score_show(self,score): self.score = str(score) print('%s' % self.score) >>> s.score_show = MethodType(score_show,s) >>> s.score_show(98) 98 但要注意的是给实例绑定的方法,只能用在该实例中 要想在所有实例中都能使用,需要绑定在类上 Student.score_show = MethodType(score_show,Student) 如果我们要限制绑定的实例,只允许绑定特定的实例可以使用__slots__: >>> # 限制绑定的属性 >>> class Std(): """定义一个学生的类""" __slots__ = ('name','age') def __init__(self,name,age): self.name = name self.age = age >>> s = Std('bob',19) >>> s.score = 98 # 当想要绑定我们定义之外的属性时就会报错 Traceback (most recent call last): File "<pyshell#29>", line 1, in <module> s.score = 98 AttributeError: 'Std' object has no attribute 'score' >>> class Std1(): def __init__(self,name,age): self.name = name self.age = age >>> st2 = Std1('Bob',19) NameError: name 'std2' is not defined >>> st2.score = 98 >>> st2.score 98 但需要注意,定义的限制属性只在当前类中起作用,在继承它的子类中不起作用 除非在子类中也定义了__slots__,那么子类将包含父类中的限制和本身定义的 3.__module__:查看这个类来自哪个模块 from m1 import t c = t.C() print(c.__module__) #m1.t 4.__del__:析构方法,高级语言不需要考虑内存的使用与释放,当内存被释放时,会触发该方法 5.__del__:内存被释放时会触发 class User: def __init__(self,name): self.name = name def __del__(self): print("我执行啦") s1 = User("alxe") # del s1.name # ---------> # print("--------->") #我执行啦 del s1 #我执行啦 # 只有删除实例时才会触发, # 上面也触发是因为程序结束了,内存也被回收了 print("------------->") #-------------> 6.数据描述符:本质上是一个类,用来在其他类的类属性中调用,来描述类属性,之后类属性的操作都有这个描述符来管理 注意事项: 1.描述符本身应定义成新式类,被代理的类也应该是新式类 2.必须把描述符定义成这个类的类属性,不能定义到构造函数中 3.必须严格遵循优先级 # 描述符的优先级 """ 类属性>数据描述符(至少有__get__和__set__)>实例属性>非数据描述符(只有__get__方法)>__getattr__ """ class Foo: """这就是定义了一个描述符""" def __get__(self, instance, owner): print("====>__get__") def __set__(self, instance, value): print("====>__set__") def __delete__(self, instance): print("====>__delete__") class Date: x = Foo() # 描述符必须定义在另一个类里面,被描述的属性调用、设置、删除都只会触发描述符中的定义的方法 b = Date() b.x # ====>__get__ b.x = 1 # ====>__set__ del b.x #====>__delete__ 7.__enter__和__exit__:上下文管理协议 with open("文件名") as f: "代码块" 这个操作会将文件加载到内存,并自动回收,就是用上下文管理协议实现的 举例: class Open: def __init__(self,name): self.name = name def __enter__(self): print("====>enter") def __exit__(self, exc_type, exc_val, exc_tb): print("====>exit") print(exc_type) #<class 'NameError'> print(exc_val) #name 'skdvuhsod' is not defined print(exc_tb) #<traceback object at 0x00000273E0BAED48> return True # with Open("a.txt") as f: # print("........") """ ====>enter ........ ====>exit """ # 当文件操作中出现异常 with Open("a.txt") as f: print("------------") print(skdvuhsod) """ 一个异常就由这三部分组成,异常类、异常值和追踪信息 <class 'NameError'> name 'skdvuhsod' is not defined <traceback object at 0x00000273E0BAED48> """ print("-----------") # 当出现异常后,会直接触发__exit__,之后的语句都不会执行 print("34134141") print("aadsdas") # 文件操作代码块出现异常时,当__exit__返回True时,异常会被吞掉,程序会继续执行, """ ====>enter ------------ ====>exit <class 'NameError'> name 'skdvuhsod' is not defined <traceback object at 0x000002311AA6ED48> aadsdas # __exit__返回True,回收文件,程序继续执行 """ 8.元类:既然类是一个对象,那么就也有产生类的类,就是元类(type) # metaclass:元类就是类的类 # class Foo: # pass # s = Foo() # print(type(s)) #<class '__main__.Foo'> # print(type(Foo)) #<class 'type'> type就是元类,我们定义的类都是由它生成的 # 那么我们就可以用type生成一个类 # def __init__(self,name,age): # self.name = name # self.age = age # Foo = type("Foo",(object,),{"__init__":__init__}) # 三个参数,类名、继承的类,属性 # f1 = Foo('alxe',10) # print(f1.__dict__) #{'name': 'alxe', 'age': 10} # 下面我们来自定制一个元类 class Mytype(type): def __init__(self,a,b,c): pass #self:【<class '__main__.Foo'>】a:【Foo】,b:【()】c:【{'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0x000002C42459DBF8>}】 def __call__(self, *args, **kwargs): #print(args,kwargs) #('alxe',) {} obj = object.__new__(self) # self就是Foo,这里使用Foo创建一个对象 self.__init__(obj,*args,**kwargs) # 调用Foo的__init__,为生成的对象添加数据属性 return obj class Foo(metaclass=Mytype): #"metclass=":声明元类 def __init__(self,name): self.name = name f = Foo('alxe') #执行类名()就会触发元类的__call__ f1 = Foo("python") print(f.name) print(f.__dict__) print("=============") print(f1.name) print(f1.__dict__)