作业24
1、在元类中控制把自定义类的数据属性都变成大写
class Mymeta(type):
def __init__(self, class_name, class_base, class_dict):
super().__init__(self)
self.__name__ = class_name
self.class_base = class_base
def __new__(cls, class_name, class_base, class_dict):
new_class_dict = {}
for k, v in class_dict.items():
if callable(v) or k.startswith("__"):
# if not isinstance(v,str) or k.startswith('__'):
new_class_dict[k] = v
else:
new_class_dict[k.upper()] = v
class_dict = new_class_dict
return type.__new__(cls, class_name, class_base, class_dict)
def __call__(self, *args, **kwargs):
class_obj = self.__new__(self, *args, **kwargs)
self.__init__(class_obj, *args, **kwargs)
return class_obj
class People(object,metaclass=Mymeta):
flag = True
msg = "fdsfsa"
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print(f"{self.name}---{self.age}")
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
print(People.__dict__)
print(People.__bases__)
print(People.class_base)
print(People)
print(People.__name__)
2、在元类中控制自定义的类无需__init__方法
1.元类帮其完成创建对象,以及初始化操作;
2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument
3.key作为用户自定义类产生对象的属性,且所有属性变成大写
class Mymeta(type):
def __init__(self, class_name, class_base, class_dict):
self.__name__ = class_name
self.class_base = class_base
def __new__(cls, class_name, class_base, class_dict):
return type.__new__(cls, class_name, class_base, class_dict)
def __call__(self, *args, **kwargs):
class_obj = self.__new__(self, *args, **kwargs)
if args:
raise TypeError("不能传入位置参数must use keyword argument")
for k,i in kwargs.items():
class_obj.__dict__[k.upper()] = i
return class_obj
class People(object,metaclass=Mymeta):
flag = True
msg = "fdsfsa"
# def say(self):
# print(f"{self.name}---{self.age}")
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
person1 = People(name = "wu",age=18)
print(person1.NAME)
3、在元类中控制自定义的类产生的对象相关的属性全部为隐藏属性
class Mymeta(type):
def __init__(self,class_name,class_base,class_dict):
self.class_name = class_name
self.class_base = class_base
self.class_dict = class_dict
def __new__(cls,*args, **kwargs):
return type.__new__(cls,*args, **kwargs)
def __call__(self, *args, **kwargs):
class_obj = self.__new__(self,*args, **kwargs)
self.__init__(class_obj,*args, **kwargs)
new_dict = {}
for k,v in kwargs.items():
if not k.startswith("__"):
k = f"_{self.class_name}__{k}"
new_dict[k] = v
class_obj.__dict__ = new_dict
return class_obj
class People(object,metaclass=Mymeta):
flag = True
msg = "fdsfsa"
def __init__(self,name, age):
self.name = name
self.age = age
def say(self):
print(f"{self.name}---{self.age}")
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
person1 = People(name = "wu",age=18)
print(person1.__dict__)
4、基于元类实现单例模式
单例:即单个实例,指的是同一个类实例化多次的结果指向同一个对象,用于节省内存空间
如果我们从配置文件中读取配置来进行实例化,在配置相同的情况下,就没必要重复产生对象浪费内存了
settings.py文件内容如下
HOST='1.1.1.1'
PORT=3306
import settings
class Mymeta(type):
def __init__(self,*args,**kwargs):
self.mysql_obj = object.__new__(self)
self.__init__(self.mysql_obj,settings.HOST,settings.PORT)
super().__init__(*args,**kwargs)
def __call__(self, *args, **kwargs):
if args or kwargs:
obj = object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj
return self.mysql_obj
class Mysql(metaclass=Mymeta):
def __init__(self,host,port):
self.host=host
self.port=port
obj1=Mysql('1.1.1.2',3306)
obj2=Mysql('1.1.1.3',3307)
obj3 = Mysql()
obj4 = Mysql()
print(obj1 is obj2) #False
print(obj3 is obj4) #False