一切源自于一句话:python中一切皆为对象
一:元类介绍
元类=》OldboyTeacher类=》obj
class OldboyTeacher ( object ) :
school = 'oldboy'
def __init__ ( self, name, age) :
self. name = name
self. age = age
def say ( self) :
print ( '%s says welcome to the oldboy to learn Python' % self. name)
obj = OldboyTeacher( 'egon' , 18 )
print ( type ( OldboyTeacher) )
结论:默认的元类是type,默认情况下我们用class关键字定义的类都是由type产生的
二:class关键字底层的做了哪些事
1、先拿到一个类名
class_name = "OldboyTeacher"
2、然后拿到类的父类
class_bases = ( object , )
3、再运行类体代码,将产生的名字放到名称空间中
class_dic = { }
class_body = """
school = 'oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('%s says welcome to the oldboy to learn Python' % self.name)
"""
exec ( class_body, { } , class_dic)
4、调用元类(传入类的三大要素:类名、基类、类的名称空间)得到一个元类的对象,然后将元类的对象赋值给变量名OldboyTeacher,oldboyTeacher就是我们用class自定义的那个类
OldboyTeacher = type ( class_name, class_bases, class_dic)
三:自定义元类
class Mymeta ( type ) :
pass
class OldboyTeacher ( object , metaclass= Mymeta) :
school = 'oldboy'
def __init__ ( self, name, age) :
self. name = name
self. age = age
def say ( self) :
print ( '%s says welcome to the oldboy to learn Python' % self. name)
1 、先拿到一个类名:
`"OldboyTeacher" `
2 、然后拿到类的父类:
( object , )
3 、再运行类体代码,将产生的名字放到名称空间中{ . . . }
4 、调用元类(传入类的三大要素:类名、基类、类的名称空间)得到一个元类的对象,然后将元类的对象赋值给变量名OldboyTeacher, oldboyTeacher就是我们用class 自定义的那个类
OldboyTeacher = Mymeta( "OldboyTeacher" , ( object , ) , { . . . } )
'' '
四:自定义元类来控制OldboyTeacher类的产生
import re
class Mymeta ( type ) :
def __init__ ( self, class_name, class_bases, class_dic) :
if not re. match( "[A-Z]" , class_name) :
raise BaseException( "类名必须用驼峰体" )
if len ( class_bases) == 0 :
raise BaseException( "至少继承一个父类" )
doc= class_dic. get( '__doc__' )
if not ( doc and len ( doc. strip( ) ) > 0 ) :
raise BaseException( "必须要有文件注释,并且注释内容不为空" )
class OldboyTeacher ( object , metaclass= Mymeta) :
"""
adsaf
"""
school = 'oldboy'
def __init__ ( self, name, age) :
self. name = name
self. age = age
def say ( self) :
print ( '%s says welcome to the oldboy to learn Python' % self. name)
'' '
五:自定义元类来控制OldboyTeacher类的调用
import re
class Mymeta ( type ) :
def __init__ ( self, class_name, class_bases, class_dic) :
if not re. match( "[A-Z]" , class_name) :
raise BaseException( "类名必须用驼峰体" )
if len ( class_bases) == 0 :
raise BaseException( "至少继承一个父类" )
doc = class_dic. get( '__doc__' )
if not ( doc and len ( doc. strip( ) ) > 0 ) :
raise BaseException( "必须要有文件注释,并且注释内容不为空" )
def __call__ ( self, * args, ** kwargs) :
tea_obj = object . __new__( self)
self. __init__( tea_obj, * args, ** kwargs)
tea_obj. __dict__ = { "_%s__%s" % ( self. __name__, k) : v for k, v in tea_obj. __dict__. items( ) }
return tea_obj
class OldboyTeacher ( object , metaclass= Mymeta) :
"""
adsaf
"""
school = 'oldboy'
def __init__ ( self, name, age) :
self. name = name
self. age = age
def say ( self) :
print ( '%s says welcome to the oldboy to learn Python' % self. name)
res = OldboyTeacher( 'egon' , 18 )
print ( res. __dict__)
调用OldboyTeacher类做的事情:
1 、先创建一个老师的空对象
2 、调用老师类内的__init__方法,然后将老师的空对象连同括号内的参数的参数一同传给__init__
3 、将初始化好的老师对象赋值给变量名res
六:单例模式
实现方式1:classmethod
import settings
class MySQL :
__instance = None
def __init__ ( self, ip, port) :
self. ip = ip
self. port = port
@classmethod
def singleton ( cls) :
if cls. __instance:
return cls. __instance
cls. __instance = cls( settings. IP, settings. PORT)
return cls. __instance
obj3 = MySQL. singleton( )
print ( obj3)
obj4 = MySQL. singleton( )
print ( obj4)
方式2:元类
import settings
class Mymeta ( type ) :
__instance = None
def __init__ ( self, class_name, class_bases, class_dic) :
self. __instance= object . __new__( self)
self. __init__( self. __instance, settings. IP, settings. PORT)
def __call__ ( self, * args, ** kwargs) :
if args or kwargs:
obj = object . __new__( self)
self. __init__( obj, * args, ** kwargs)
return obj
else :
return self. __instance
class MySQL ( metaclass= Mymeta) :
def __init__ ( self, ip, port) :
self. ip = ip
self. port = port
obj3 = MySQL( )
obj4 = MySQL( )
print ( obj3 is obj4)
方式3:装饰器
import settings
def outter ( func) :
_instance = func( settings. IP, settings. PORT)
def wrapper ( * args, ** kwargs) :
if args or kwargs:
res= func( * args, ** kwargs)
return res
else :
return _instance
return wrapper
@outter
class MySQL :
def __init__ ( self, ip, port) :
self. ip = ip
self. port = port
obj3 = MySQL( )
obj4 = MySQL( )
print ( obj3 is obj4)
了解:属性查找
class Mymeta ( type ) :
n= 444
class Bar ( object ) :
pass
class Foo ( Bar) :
pass
class OldboyTeacher ( Foo, metaclass= Mymeta) :
school= 'oldboy'
def __init__ ( self, name, age) :
self. name= name
self. age= age
def say ( self) :
print ( '%s says welcome to the oldboy to learn Python' % self. name)
print ( OldboyTeacher. n)