Ⅰ 元类
类的爹就是元类 #很通俗易懂
而在python中又有一切皆对象说法
那么类是如何成为对象的呢?即调用元类,得到对象(类,或者说自定义的类)
默认的元类的type,默认情况下我们用class关键字定义的类都是由type产生的
# python中一切皆对象
# 元类介绍
# 元类=>OldboyTeacher类 =>obj 对象
class OldboyTeacher(object):
school = 'oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('>>>>')
obj = OldboyTeacher('egon', 16) # 调用类OldboyTeacher类得到类的对象obj
# 调用元类得到OldboyTeacher类(对象)
问题又来了,class关键字是如何产生类的呢?
# class关键字底层做了哪些事
# 先拿到一个类名
class_name = 'Oldboy'
# 然后拿到类的父亲
class_bases = (object,)
# 再运行类体代码,将产生的名字放到名称空间中
class_dic = {}
class_body = """
school = 'oldboy'
def __init__(self,name,age):
self.name = name
self.age = age
def say(self):
print('>>>')
"""
exec(class_body,{},class_dic)
print(class_dic)
# 调用元类(传入类的三大要素:类名,基类,类的名称空间,得到一个元类的对象
# 然后将元类的对象赋值给变量名OldboyTeacher就是我们用class自定义的那个类)
OldboyTeacher = type(class_name,class_bases,class_dic)
自定义元类
只有继承了type类的类才是自定义的元类
class Mymeta(type):
pass
#1>先拿到一个类名:'egon'
#2>然后拿到类的父亲:(object,)
#3>再运行类体代码,将产生的名字放到名称空间中{...}
#4>调用元类(传入类的三大要素:类名,基类,类的名称空间)
# 得到一个元类的对象,然后将元类的对象赋值给变量名
单例模式
一个类被多次调用产生的多个对象,但是对象内的数据都是一样的,这样就额外占用了内存空间,解决这个问题的方式就称为类的单例模式
class MyQLE():
def __init__(self,name,age):
self.name = name
self.age = age
obj = MyQLE('egon',19)
obj2 = MyQLE('egon',19)
print(obj) # 两个对象数据一样,但是占用了两份内存空间
print(obj2)
方式一:classmethod功能
import setting # 例如从一个文件中取出固定的值
class MyQLE():
__instance = None # 定义一个变量
def __init__(self,name,age):
self.name = name
self.age = age
@classmethod
def singleton(cls): # 写成类方法
if cls.__instance: # 调用的时候判断变量有值,直接返回已存在的值,不用二次调用产生新的
return cls.__instance
else:
cls.__instance = cls(setting.name,setting.age) # 如果没有,将类实例化得到对象并赋值,返回
return cls.__instance
obj2 = MyQLE.singleton()
print(obj2)
obj = MyQLE.singleton()
print(obj)
方式二:使用元类
# 方式二 : 使用元类
import setting
class Mymeta(type):
__instance = None
def __init__(self,class_name,class_banses,class_dic):
self.__instance = object.__new__(self) #类的对象
self.__init__(self.__instance,setting.name,setting.age)
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,name,age):
self.name = name
self.age = age
obj2 = MySQL()
obj3 = MySQL()
print(obj2)
print(obj3)
方式三:使用装饰器
# 方式三: 使用装饰器
import setting
def outter(func):
_instance = func(setting.name,setting.age)
def wrapper(*args,**kwargs):
if args or kwargs:
return func(*args,**kwargs)
else:
return _instance
return wrapper
@outter
class MySQL:
def __init__(self,name,age):
self.name = name
self.age = age
obj1 = MySQL()
obj2 = MySQL()
print(obj2)
print(obj1)
网友评论