补充内置函数:
isinstance和issubclass
class People: def run(self): print('people run') class Student(People): print('student') obj=People() print(isinstance(obj,People)) # isinstance(对象,类)判断一个对象的类型 print(issubclass(Student,People)) # issubclass(子类,类)判断是否是子类
反射:
下述四个函数专门用来操作类与对属性的
hasattr() getattr() setattr() delattr()
通过字符串来操作类与对象的属性,这种方式被称为反射
class School: school='oldboy' def __init__(self,name,age): self.name=name self.age=age obj=School('egon',20) print(hasattr(obj,'school')) print(hasattr(obj,'name')) # hasattr(对象,Name)判断属性是否属于这个类的!!!注意Name一定要是字符串 print(getattr(obj,'school',None)) print(getattr(obj,'age',None)) # getattr(对象,Name,默认值)得到属性的值,默认值是找不到属性的时候,返回None setattr(School,'x',1) print(School.__dict__)#{'__module__': '__main__', 'school': 'oldboy', '__init__': <function School.__init__ at 0x000001F40F6198C8>, '__dict__': <attribute '__dict__' of 'School' objects>, '__weakref__': <attribute '__weakref__' of 'School' objects>, '__doc__': None, 'x': 1} setattr(obj,"age",18) print(obj.__dict__)#{'name': 'egon', 'age': 18} # setattr(对象,属性,属性的值)打印返回的值是None delattr(obj,'name') print(obj.__dict__)#{'age': 18} # delattr(对象,属性)打印返回的值是None
__str__内置
# __str__在打印的时候被触发 class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __str__(self): return ''' 姓名:%s 名字:%s 性别:%s '''%(self.name,self.age,self.sex) obj=People('egon',18,'male') print(obj)
__del__内置
# __del__在对象被删除的条件下,自动执行 class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __del__(self): print('__del__') del obj.name obj=People('egon',18,'male') # __del__结果
介绍一下exec
code=""" global x x=0 y=2 """#(字符串的形式,如果你不指定默认存为局部名称空间) global_dic={'x':100000}#(全局名称空间) local_dic={}#(局部名称空间) exec(code,global_dic,local_dic)#exec(字符串,全局名称空间,局部名称空间)如果名称空间直接放一个空字典 则为空 print(global_dic) print(local_dic)
元类:类的类就是元类
我们用class定义的类使用来产生我们自己的对象
内置元类type是用来专门产生class定义的类的
Chinese=type(...)#(类的类,元类) class Chinese:#(类) country="China" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def speak(self): print('%s speak Chinese' %self.name) print(Chinese) p=Chinese('egon',18,'male') print(type(p))#(直接打印p的到的是类型和内存地址) print(type(Chinese))
2、用内置的元类type,来实例化得到我们的
class_name='Chinese' class_bases=(object,) class_body=""" country="China" def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def speak(self): print('%s speak Chinese' %self.name) """ class_dic={} exec(class_body,{},class_dic) # 类的三大要素(类名,父类,局部名称空间) # print(class_name,class_bases,class_dic) Chinese=type(class_name,class_bases,class_dic) print(Chinese) p=Chinese('egon',18,'male') print(p.name,p.age,p.sex)
3、储备知识__call__
调用对象,则会自动触发对象下的绑定方法__call__的执行,
然后将对象本身当作第一个参数传给self,将调用对象时括号内的值
传给*args与**kwargs
class Foo: def __init__(self): pass def __str__(self): return '123123' def __del__(self): pass def __call__(self, *args, **kwargs): print('__call__',args,kwargs) obj=Foo() print(obj) obj(1,2,3,a=1,b=2,c=3) #
4 、自定义元类:
class Mymeta(type): # 来控制类Foo的创建 def __init__(self,class_name,class_bases,class_dic): #self=Foo # print(class_name) # print(class_bases) # print(class_dic) if not class_name.istitle(): raise TypeError('类名的首字母必须大写傻叉') if not class_dic.get('__doc__'): raise TypeError('类中必须写好文档注释,大傻叉') super(Mymeta,self).__init__(class_name,class_bases,class_dic) # 控制类Foo的调用过程,即控制实例化Foo的过程 def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={} # print(self) # print(args) # print(kwargs) #1 造一个空对象obj obj=object.__new__(self) #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__ self.__init__(obj,*args,**kwargs) return obj #Foo=Mymeta('Foo',(object,),class_dic) class Foo(object,metaclass=Mymeta): """ 文档注释 """ x=1 def __init__(self,y): self.y=y def f1(self): print('from f1') obj=Foo(1111) #Foo.__call__() print(obj) print(obj.y) print(obj.f1) print(obj.x)
单列模式
import settings class MySQL: __instance=None def __init__(self,ip,port): self.ip=ip self.port=port @classmethod def singleton(cls): if not cls.__instance: obj=cls(settings.IP, settings.PORT) cls.__instance=obj return cls.__instance obj1=MySQL('1.1.1.2',3306) obj2=MySQL('1.1.1.3',3307) obj3=MySQL('1.1.1.4',3308) # obj4=MySQL(settings.IP,settings.PORT) # print(obj4.ip,obj4.port) obj4=MySQL.singleton() obj5=MySQL.singleton() obj6=MySQL.singleton() print(obj4 is obj5 is obj6)