Day24 the reflecting object oriented metaclass

1. Reflection

Reflecting means should have an object can be detected, modify, increase their ability to attribute

It is reflected by the string operation property

Relates to four functions, these four functions built-in function is normal, there is no double underlining, print, etc. and there is no difference in the use of the method

hasattr, getattr, setattr, delattr (their specific use and function codes, see the following)

. 1  class the Person:
 2      DEF  the __init__ (Self, name, Age):
 . 3          the self.name = name
 . 4          self.age = Age
 . 5  
. 6 P = the Person ( ' sxc ' , 18 is )
 . 7  
. 8  IF the hasattr (P, ' name ' ) :   # determines whether or not an object exists a property 
. 9      Print (getattr (P, ' name ' ))   # this value is returned as return out 
10  
. 11  Print (getattr (P, ' Gender ', None))   # If this latter value may not give him a default value 
12 is  
13 is setattr (P, ' ID ' , 177)   # can impart new properties for the object 
14  Print (p.id)
 15  
16 delattr (P , ' ID ' )   # attribute object may be deleted 
. 17  Print (p.id)

scenes to be used:

In fact, reflected on the additions and deletions to change the properties of the check, but if the direct use of the built-in __dict__ to operate, grammar cumbersome, difficult to understand

If the other party can not determine whether the properties and methods I need

 

Simple frame design

Framework that has achieved the most basic framework is all part of the same project has been completed. Reflection is known as the cornerstone of the framework, the framework designers can not know in advance the user object in the end it is how the design, so the object is provided to the user to use the normal framework must be verified by the judge after judge to verify that reflection to do thing

Requirements: achieve a small frame for processing user terminal instructions

1  # frame portion 
2  DEF RUN (plugin):
 . 3      the while True:
 . 4          cmd = INPUT ( ' Enter your order >>>: ' ) .strip ()
 . 5          IF cmd == ' Exit ' :
 . 6              BREAK 
. 7          #   not Analyzing the parameters passed, reflection needs to be added is determined 
. 8          IF the hasattr (plugin, cmd):   # remove the corresponding instruction 
. 9              FUNC = getattr (plugin, cmd)
 10              FUNC ()   # execution instruction processing 
. 11          the else :
 12 is              Print (" Please enter the correct instruction ' )
 13 is      Print ( " exit the program ' )
 14  
15  # intercept module class name, and the path from the system configuration file 
16 The module_path, settings.CLASS_PATH.rsplit class_name = ( ' . ' ,. 1 )
 . 17  # Take the module 
18 is MK = importlib.import_module (the module_path)
 . 19  # get class 
20 is CLS = getattr (MK, class_name)
 21 is  # instantiate the object 
22 is obj = CLS ()
 23 is  # call frame 
24 RUN (obj)
Framework of the project and run the code
# Profile path 

CLASS_PATH = ' lib.plugin.WinCmd '
. 1  class wincmd:
 2      DEF CD (Self):
 . 3          Print ( ' into the file ' )
 . 4  
. 5      DEF delate (Self):
 . 6          Print ( ' deletion library foot ' )
 . 7  
. 8      DEF the dir (Self):
 . 9          Print ( ' file list ' )
 10  
. 11  
12 is  class LinuxCmd:
 13 is      DEF CD (Self):
 14          Print ( ' into the file ' )
 15  
16     DEF RM (Self):
 . 17          Print ( ' deletion library foot ' )
 18 is  
. 19      DEF LS (Self):
 20 is          Print ( ' Files ' )
Plug-in code

 

2. metaclass metaclass

For creating a class of classes called metaclasses

Everything in python objects, classes are objects

The object is generated by instantiating the class, if the class is an object, it certainly class object instantiated by another class is generated

All classes are by default metaclass type

Metaclass verification:

1  # metaclass verification 
2  class the Person:
 . 3      Pass 
. 4  
. 5 P = the Person ()
 . 6  
. 7  # Type type method may view objects 
. 8  Print (type (P))
 . 9  Print (type (the Person))

 

Learning Objectives yuan class:

Highly customizable a class, can be controlled to a particular class name must be written in a fixed format

We can initialize method, as long as the Yuan class and override inherited __init__ method which can achieve demand

案例,通过元类限制类的名字必须以大驼峰的方式命名

 1 # 继承元类可以高度定义一个子类
 2 class MyType(type):
 3     def __init__(self,cls,bases,dict):
 4         super().__init__(cls,bases,dict)
 5         if not cls.istitle():
 6             raise Exception('请小写')
 7 # 生成两个子类
 8 class Pig(metaclass= MyType):
 9     pass
10 
11 class duck(metaclass= MyType):
12     pass

Pig类可以通过,duck类并未大写,报错

 

元类中call方法

当调用类对象时会自动执行元类中的__call__方法,并将这个类本身作为第一个参数传入,以及后面的参数

覆盖元类中的call之后,就无法产生对象.必须调用super().__call__来完成对象的创建,并返回其返回值

 1 # __call__是用来实例化对象返回值的
 2 class MyType(type):
 3     def __call__(self, *args, **kwargs):
 4         print('元类call')
 5         print(args)
 6         print(kwargs)
 7 
 8 class Person(metaclass=MyType):
 9     def __init__(self,name):
10         self.name = name
11 
12 p = Person('sxc',age = 18)
13 print(p)

当我们覆盖了元类的__call__方法,他的返回值就变成了None,说明__call__是用来实例化对象传值的

案例1:把子类中的所有属性都改为大写

 1 # 把子类的所有属性都改成大写
 2 class MyType(type):
 3     def __call__(self, *args, **kwargs):
 4         new_args = []  # 定义一个新列表
 5         for a in args:  # 循环输出旧列表中的内容
 6             new_args.append(a.upper())  # 添加到新列表中
 7         return super().__call__(*new_args,**kwargs)
 8 
 9 
10 class Person(metaclass=MyType):
11     def __init__(self,name):
12         self.name = name
13 
14 
15 p = Person('sxc')
16 p1 = Person('aabbcceeff')
17 print(p.name)
18 print(p1.name)

案例2:要求创建对象时只能关键字传参

 1 # 要求:只允许关键字传参
 2 class MyType(type):
 3     def __call__(self, *args, **kwargs):  # 覆盖元类的__call__方法
 4         if args:
 5             raise Exception('不允许直接传参')  # 当直接传参时报错
 6         return super().__call__(*args,**kwargs)
 7 
 8 class Person(metaclass= MyType):
 9     def __init__(self,name,age):
10         self.name = name
11         self.age = age
12 
13 p1 = Person(name = 'sxc',age = 18)
14 print(p1.name,p1.age)
15 p = Person('sxc',18)

注意:一旦覆盖了call必须调用父类的call方法来产生对象并返回这个对象

__init__方法和__call__方法的使用场景:

  当想要控制对象的创建过程时,就覆盖call方法

  当想要控制类的创建过程时,就覆盖init方法

 

补充new方法

当创建类对象时,会首先窒息感元类中的__new__方法,拿到一个空对象,然后自动调用__init__来初始化

 1 # new方法
 2 class Mytype(type):
 3     def __new__(cls, *args, **kwargs):
 4         print(cls)  # 元类自己
 5         print(args)  # 创建类需要的几个参数  类名,基类,名称空间
 6         print(kwargs)  # 空的值
 7         print('new run')
 8         return super().__new__(cls, *args, **kwargs)
 9 
10     def __init__(self,a,b,c):
11         super().__init__(a,b,c)
12         print('init run')
13 
14 class A(metaclass= Mytype):  # new方法和call方法在类生成时自动执行
15     pass
16 
17 print(A)  # 类对象本身

注意:当我们覆盖了__call__方法必须保证new方法有返回值并且是对应的类对象

 

单例设计模式

单例是为了节省资源,当一个类的所有对象属性全部相同时,没有必要创建多个对象

单例实现

 1 # 单例的实现
 2 class Single(type):
 3     def __call__(self, *args, **kwargs):
 4         if hasattr(self,'obj'):  # 判断是否有已存在的对象
 5             return getattr(self,'obj')  # 有就返回
 6         obj = super().__call__(*args,**kwargs)  # 没有就创建
 7         self.obj = obj  # 存到类中,方便下次查找
 8         return obj
 9 
10 class Person(metaclass=Single):
11     def __init__(self,name):
12         self.name = name
13 
14 # 只会创建初始的对象
15 p = Person('sxc')
16 print(p.name)
17 p1 = Person('zzj')
18 print(p1.name)
19 p2 = Person('zzp')
20 print(p2.name)
21 p3 = Person('lzx')
22 print(p3.name)
23 p4 = Person('zkj')
24 print(p4.name)

 

元类练习:

 1 '''
 2 1.使用元类实现检测类中的所有属性 包括类属性和方法,将名字存储到类的名称空间中
 3 例如:有student类  有eat函数 和school属性  ,获取这两个名字 存储到一个叫做attrs的列表中,并将列表作为student类的属性
 4 使得student类可以通过访问attrs来获取自身所有的属性名字
 5 '''
 6 class MyType(type):
 7     def __init__(self,cls,bases,dict):
 8         attr = []
 9         for i in dict:  # 遍历字典中的类属性
10             if i == 'school' or i == 'eat':
11                 attr.append(i)  # 把他添加到新的列表中去
12         self.attr = attr  # 添加到类属性中
13         super().__init__(cls,bases,dict)
14 
15 class Student(metaclass=MyType):
16     school = 'oldboy'
17 
18     def eat(self):
19         print('吃东西')
20 
21 stu = Student()
22 print(stu.attr)
练习

 

Guess you like

Origin www.cnblogs.com/sxchen/p/11272885.html