python-study-24
总结
内置函数 isinstance issubclass 反射 字符串 hasattr getattr setattr delattr 自定义内置方法类定制类的功能 __str__ __del__ 自定义元类 控制 mymeta(type) 类产生过程 __init__ 加判断 类调用过程 __call__ __new__ __init__ return
复习
上节课复习: 1、封装 class Foo: __n=111 #_Foo__n def __init__(self,x): self.__x=x #self._Foo__x def func(self): self.__x #self._Foo__x Foo.__n #Foo._Foo__n obj=Foo() obj.__x Foo.__n Foo.__m=111 obj,__y=22 class Foo: __x=111 #_Foo__x class Bar(Foo): __x=222 #_Bar__x 2、property 可以将类内的函数伪装成一个数据属性去访问 class Foo: def __init__(self,x): self.__x=x #新的写法 @property def x(self): return self.__x @x.setter def x(self,val) self.__x=val @x.deleter def x(self): del self.__x # 古老的写法 def get_x(self): pass def set_x(self,val): pass def del_x(self): pass x=property(get_x,set_x,del_x) obj=Foo(10) obj.x obj.x=1 del obj.x 3、绑定方法与非绑定方法 @classmethod @staticmethod 今日内容: 1、反射 hasattr setattr getattr delattr 2、内置的方法 __str__ __del__ 3、元类(*****) 用于实例化产生类的类称之为元类 __call__ __new__ 单例模式
内置函数
# class Foo: # pass # # obj=Foo() # # print(isinstance(obj,Foo)) # 在python3中统一类与类型的概念 # d={'x':1} #d=dict({'x':1} #) # print(type(d) is dict) # print(isinstance(d,dict)) # issubclass() class Parent: pass class Sub(Parent): pass print(issubclass(Sub,Parent)) print(issubclass(Parent,object))
反射
''' 1、什么是反射 通过字符串来操作类或者对象的属性 2、如何用 hasattr getattr setattr delattr ''' class People: country='China' def __init__(self,name): self.name=name def eat(self): print('%s is eating' %self.name) peo1=People('egon') # print(hasattr(peo1,'name')) # print(hasattr(peo1,'eat')) #peo1.eat # print(getattr(peo1,'eat')) #peo1.eat # print(getattr(peo1,'country',None)) # setattr(peo1,'age',18) #peo1.age=18 # print(peo1.age) # print(peo1.__dict__) # delattr(peo1,'name') #del peo1.name # print(peo1.__dict__) class Ftp: def __init__(self,ip,port): self.ip=ip self.port=port def get(self): print('GET function') def put(self): print('PUT function') def run(self): while True: choice=input('>>>: ').strip() # print(choice,type(choice)) # if hasattr(self,choice): # method=getattr(self,choice) # method() # else: # print('输入的命令不存在') method=getattr(self,choice,None) if method is None: print('输入的命令不存在') else: method() conn=Ftp('1.1.1.1',23) conn.run()
自定义内置方法类定制类的功能
#1、__str__方法 # class People: # def __init__(self,name,age): # self.name=name # self.age=age # # #在对象被打印时,自动触发,应该在该方法内采集与对象self有关的信息,然后拼成字符串返回 # def __str__(self): # # print('======>') # return '<name:%s age:%s>' %(self.name,self.age) # obj=People('egon',18) # obj1=People('alex',18) # print(obj) #obj.__str__() # print(obj) #obj.__str__() # print(obj) #obj.__str__() # print(obj1) #obj1.__str__() # d={'x':1} #d=dict({'x':1}) # print(d) #1、__del__析构方法 # __del__会在对象被删除之前自动触发 class People: def __init__(self,name,age): self.name=name self.age=age self.f=open('a.txt','rt',encoding='utf-8') def __del__(self): # print('run=-====>') # 做回收系统资源相关的事情 self.f.close() obj=People('egon',18) print('主')
元类
''' 1、什么是元类 在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象 负责产生该对象的类称之为元类,即元类可以简称为类的类 class Foo: # Foo=元类() pass 2、为何要用元类 元类是负责产生类的,所以我们学习元类或者自定义元类的目的 是为了控制类的产生过程,还可以控制对象的产生过程 3、如何用元类 ''' #1、储备知识:内置函数exec的用法 # cmd=""" # x=1 # def func(self): # pass # """ # class_dic={} # exec(cmd,{},class_dic) # # print(class_dic) #2、创建类的方法有两种 # 大前提:如果说类也是对象的化,那么用class关键字的去创建类的过程也是一个实例化的过程 # 该实例化的目的是为了得到一个类,调用的是元类 #2.1 方式一:用的默认的元类type # class People: #People=type(...) # country='China' # def __init__(self,name,age): # self.name=name # self.age=age # # def eat(self): # print('%s is eating' %self.name) # print(type(People)) #2.1.1 创建类的3个要素:类名,基类,类的名称空间 class_name='People' class_bases=(object,) class_dic={} class_body=""" country='China' def __init__(self,name,age): self.name=name self.age=age def eat(self): print('%s is eating' %self.name) """ exec(class_body,{},class_dic) # 准备好创建类的三要素 # print(class_name) # print(class_bases) # print(class_dic) # People=type(类名,基类,类的名称空间) # People1=type(class_name,class_bases,class_dic) # print(People1) # obj1=People1('egon',18) # print(People) # obj=People('egon',18) # # obj1.eat() # obj.eat() ''' #2.2 方式二:用的自定义的元类 class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类 def __init__(self,class_name,class_bases,class_dic): print(self) #现在是People print(class_name) print(class_bases) print(class_dic) super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能 # 分析用class自定义类的运行原理(而非元类的的运行原理): #1、拿到一个字符串格式的类名class_name='People' #2、拿到一个类的基类们class_bases=(obejct,) #3、执行类体代码,拿到一个类的名称空间class_dic={...} #4、调用People=type(class_name,class_bases,class_dic) class People(object,metaclass=Mymeta): #People=Mymeta(类名,基类们,类的名称空间) country='China' def __init__(self,name,age): self.name=name self.age=age def eat(self): print('%s is eating' %self.name) # 应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程 class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类 def __init__(self,class_name,class_bases,class_dic): if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0: raise TypeError('类中必须有文档注释,并且文档注释不能为空') if not class_name.istitle(): raise TypeError('类名首字母必须大写') super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能 class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....}) """这是People类""" country='China' def __init__(self,name,age): self.name=name self.age=age def eat(self): print('%s is eating' %self.name) ''' #3 储备知识:__call__ # class Foo: # def __call__(self, *args, **kwargs): # print(self) # print(args) # print(kwargs) # # # obj=Foo() # # # 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法 # # 该方法会在调用对象时自动触发 # obj(1,2,3,x=1,y=2) # 4、自定义元类来控制类的调用的过程,即类的实例化过程 class Mymeta(type): def __call__(self, *args, **kwargs): # print(self) # self是People # print(args) # print(kwargs) # return 123 # 1、先造出一个People的空对象 obj=self.__new__(self) # 2、为该对空对象初始化独有的属性 # print(args,kwargs) self.__init__(obj,*args,**kwargs) # 3、返回一个初始好的对象 return obj class People(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def eat(self): print('%s is eating' %self.name) def __new__(cls, *args, **kwargs): print(cls) # cls.__new__(cls) # 错误 obj=super(People,cls).__new__(cls) return obj # 分析:调用Pepole的目的 #1、先造出一个People的空对象 #2、为该对空对象初始化独有的属性 # obj1=People('egon1',age=18) # obj2=People('egon2',age=18) # print(obj1) # print(obj2) obj=People('egon',age=18) print(obj.__dict__) print(obj.name) obj.eat()