1. Control in the metaclass to change the data attributes of the custom class to uppercase
class Mymeta(type): def __new__(cls,name,bases,attrs): update_attrs={} for k,v in attrs.items(): if not callable(v) and not k.startswith('__'): update_attrs[k.upper()]=v else: update_attrs[k]=v return type.__new__(cls,name,bases,update_attrs) class Chinese(metaclass=Mymeta): country='China' tag='Legend of the Dragon' #龙的传人 def walk(self): print('%s is walking' %self.name) print(Chinese.__dict__) ''' {'__module__': '__main__', 'COUNTRY': 'China', 'TAG': 'Legend of the Dragon', 'walk': <function Chinese.walk at 0x0000000001E7B950>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None} '''
2. The __init__ method is not required to control the custom class in the metaclass
1. Metaclass to help it complete the creation of objects and initialization operations; 2. Require that the parameter passed during instantiation must be in the form of keywords, otherwise throw an exception TypeError: must use keyword argument 3.key as the attribute of the object generated by the user-defined class , And all attributes are capitalized
class Mymetaclass(type): # def __new__(cls,name,bases,attrs): # update_attrs={} # for k,v in attrs.items(): # if not callable(v) and not k.startswith('__'): # update_attrs[k.upper()]=v # else: # update_attrs[k]=v # return type.__new__(cls,name,bases,update_attrs) def __call__(self, *args, **kwargs): if args: raise TypeError('must use keyword argument for key function') obj = object.__new__(self) #创建对象,self为类Chiness for k,v in kwargs.items(): obj.__dict__[k.upper()]=v return obj class Chinese(metaclass=Mymetaclass): country='China' tag='Legend of the Dragon' #龙的传人 def walk(self): print('%s is walking' %self.name) p=Chinese(name='lili',age=18,sex='male') print(p.__dict__)
3. In the metaclass, all attributes related to the objects generated by the custom class are hidden attributes.
class Mymeta (of the type): DEF __init__ (Self, class_name, class_bases, class_dic): # Control class creates Foo's Super (Mymeta, Self). __init__ (class_name, class_bases, class_dic) DEF __call__ (Self, * args, ** kwargs ): # control calling procedure Foo, i.e. Foo generation process object . obj = Self __new__ is (Self) . Self the __init__ (obj, * args, ** kwargs) . obj the __dict__ = { ' _% S __% S ' % ( self. __name__ , k): v for k, v in obj.__dict__.items()} return obj class Foo(object,metaclass=Mymeta): # Foo=Mymeta(...) def __init__(self, name, age,sex): self.name=name self.age=age self.sex=sex obj=Foo('lili',18,'male') print(obj.__dict__)
4. Implement the singleton pattern based on metaclasses
# Step Five: Example membered single-mode based on the class # i.e. a single instance, refers to the result of the same class instantiated multiple times to the same object, to save memory space: Single Example # if we read from the configuration file Configure to instantiate. Under the same configuration, there is no need to repeatedly generate objects to waste memory. # Settings.py file content is as follows HOST = ' 1.1.1.1 ' PORT = 3306 # Method one: define a class method to achieve a singleton Mode import settings class Mysql: __instance = None def __init__ (self, host, port): self.host = host self.port = port @classmethod def singleton (cls): if not cls. __instance : cls. __instance = cls (settings.HOST, settings.PORT) return cls. __instance obj1 = Mysql ( ' 1.1.1.2 ' , 3306 ) obj2 = Mysql ( ' 1.1.1.3 ' , 3307 ) print (obj1 is obj2) # False OBJ3 = Mysql.singleton () OBJ4 = Mysql.singleton () Print (OBJ3 IS OBJ4) # True # way: custom metaclass single-mode embodiment importSettings class Mymeta (type): DEF the __init__ (Self, name, bases, DIC): # triggered when defining class Mysql # pre-fetch start profile configured to create an instance of Mysql out Self. __instance = Object. __new__ is ( Self) # generates an object Self. the __init__ (Self. __instance , settings.HOST, settings.PORT) # initialize the object # above may be synthesized in two steps following step # Self instance .__ = Super () Call .__ __ (* args, ** kwargs) super (). __init__ (name, bases, dic) def __call__ (self, * args, ** kwargs): #Trigger (...) MySQL IF args or kwargs: # with a value within args or kwargs obj = Object. __New__ (Self) Self. __Init__ (obj, * args, ** kwargs) return obj return Self. __Instance class MySQL ( = the metaclass that Mymeta): DEF the __init__ (Self, Host, Port): self.host = Host self.port = Port OBJ1 = Mysql () # did not pass the default value is read from the configuration file is instantiated, all instances should Points to a memory address obj2 = Mysql () obj3= Mysql () Print (OBJ1 IS obj2 IS OBJ3) OBJ4 = Mysql ( ' 1.1.1.4 ' , 3307 ) # third approach: Define a decorator single-mode embodiment Import Settings DEF Singleton (CLS): # CLS = Mysql _instance = cls (settings.HOST, settings.PORT) def wrapper (* args, ** kwargs): if args or kwargs: obj = cls (* args, ** kwargs) return obj return _instance return wrapper @singleton # Mysql=singleton(Mysql) class Mysql: def __init__(self,host,port): self.host=host self.port=port obj1=Mysql() obj2=Mysql() obj3=Mysql() print(obj1 is obj2 is obj3) #True obj4=Mysql('1.1.1.3',3307) obj5=Mysql('1.1.1.4',3308) print(obj3 is obj4) #False