1、在元类中控制把自定义类的数据属性都变成大写
class MyDef(type):
def __new__(cls, class_name, class_attr, class_dic):
upper_data = {}
for k,v in class_dic.items():
if not callable(v) and not k.startswith('__'):
upper_data[k.upper()] = v
else:
upper_data[k] = v
return type.__new__(cls, class_name, class_attr, upper_data)
class People(metaclass=MyDef):
time = 'now'
work = 'weekends'
print(People.__dict__)
2、在元类中控制自定义的类无需__init__方法
1.元类帮其完成创建对象,以及初始化操作;
2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument
3.key作为用户自定义类产生对象的属性,且所有属性变成大写
class MyDef(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError(' must use keyword argument')
obj = object.__new__(self)
for k,v in kwargs.items():
obj.__dict__[k.upper()] = v
return obj
class People(metaclass=MyDef):
tag = 'China'
some = 'None'
p1 = People(name = 'panda')
print(p1.__dict__)
3、在元类中控制自定义的类产生的对象相关的属性全部为隐藏属性
class Mymeta(type):
def __init__(self, class_name, class_bases, attr):
super(Mymeta, self).__init__(class_name, class_bases, attr)
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs )
obj.__dict__ = {'_%s__%s' % (self.__name__, k): v for k, v in obj.__dict__.items()}
return obj
class P(metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age
p1 = P('123','567')
print(p1._P__name)
4、基于元类实现单例模式
# settings.py文件
IP = '1.1.1.1'
PORT = 3303
方式一:定义一个类方法实现单例模式
import settings
class People:
__instance = None #用于保存实例化的状态
def __init__(self, ip, port):
self.ip = ip
self.port = port
@classmethod
def get(cls):
if cls.__instance is None:
cls.__instance = cls(settings.IP, settings.PORT)
return cls.__instance
obj1 = People.get()
obj2 = People.get()
print(obj1)
print(obj2)
# <__main__.People object at 0x00000000021BA9B0>
# <__main__.People object at 0x00000000021BA9B0>
#方式二:定义一个装饰器实现单例模式
import settings
def singlet(cls):
_instance = cls(settings.IP, settings.PORT) #先实例化一个对象
def wrapper(*args, **kwargs):
if args or kwargs:
obj = cls(*args, **kwargs)
return obj #有参数是返回后来实例化对象
return _instance #无参时,返回已经实例化好的对象
return wrapper
@singlet # MySQL=wrapper(MySQL)
class MySQL:
def __init__(self, ip, port):
self.ip = ip
self.port = port
# 没有参数时,单例模式
obj1 = MySQL()
obj2 = MySQL()
obj3 = MySQL()
obj4 = MySQL('1.1.1.1', 3303)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
# <__main__.MySQL object at 0x0000000001E6AA90>
# <__main__.MySQL object at 0x0000000001E6AA90>
# <__main__.MySQL object at 0x0000000001E6AA90>
# <__main__.MySQL object at 0x0000000001E6AB00>
#方式三:定制元类实现单例模式
import settings
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
instance = self(settings.IP, settings.PORT)
self.__instance = instance
def __call__(self, *args, **kwargs): # self=MySQL
if args or kwargs: # 有参数执行下面的代码
obj = self.__new__(self) #创造一个空对象
self.__init__(obj, *args, **kwargs) #初始化
return obj #返回对象
return self.__instance
class MySQL(metaclass=Mymeta):
def __init__(self, ip, port):
self.ip = ip
self.port = port
obj1 = MySQL()
obj2 = MySQL()
obj3 = MySQL()
obj4 = MySQL('1.2.3.1', 3305)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
# <__main__.MySQL object at 0x00000000021BAA90>
# <__main__.MySQL object at 0x00000000021BAA90>
# <__main__.MySQL object at 0x00000000021BAA90>
# <__main__.MySQL object at 0x00000000021BAB00>
方式四:利用模块导入实现单例模式
# singleton模块
import settings
class MySQL:
def __init__(self, ip, port):
self.ip = ip
self.port = port
instance = MySQL(settings.IP, settings.PORT)
#单例模块
def f1():
from singleton import instance
print(instance)
def f2():
from singleton import instance, MySQL
print(instance)
obj = MySQL('1111', 3302)
print(obj)
f1()
f2()
# <singleton.MySQL object at 0x00000000021FAA90>
# <singleton.MySQL object at 0x00000000021FAA90>
# <singleton.MySQL object at 0x00000000021FA358>