zoukankan      html  css  js  c++  java
  • python面向对象之元类

    元类

    元类(A) ---> 类(B) ---> 实例(C)

    对于实例C而言,它是对象,它的类就是类B

    对于类B而言,它其实也是对象,那它的类就是元类A

    对于元类A而言,它其实也是对象,那它的类就是自己本身

    造类

    第一阶段

    class Foo:
        count = 0
        def __init__(self,name):
            self.name = name
        def eat(self):
            print("eat")
        def run(self):
            print("run")
    
    # ------------------------------------------
    
    class_name = "Foo"		# 类名
    class_bases = (object,)	# 继承类
    class_body = """		
    count = 0
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("eat")
    def run(self):
        print("run")
    """
    class_dict = dict()		# dict属性和方法
    exec(class_body,{},class_dict)	# 将class_bady中的字符串,转化为键值对存储到class_dict中
    one = type(class_name,class_bases,class_dict)	# 使用type创建类
    
    print(one)
    print(Foo)
    
    <class '__main__.Foo'>
    <class '__main__.Foo'>
    

    这时,我们发现通过type创建出来一个和Foo相同的类one,但是这里的变量太死板了,我们还需要改变一下

    第二阶段

    class  Foo(type):
        def __init__(self,class_name,class_bases,class_dict):
            if not class_dict.get("__doc__"):
                raise  TypeError("请加上注释")
            super().__init__(class_name,class_bases,class_dict)
    
    
    class person(object,metaclass=Foo):
        
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def run(self):
            print("run")
    
        def eat(self):
            print("eat")
    
    
    one = person('plf',18,'男')
    print(one.name)
    print(one.age)
    print(one.sex)
    
    Traceback (most recent call last):
      File "E:/***/***/***/test1.py", line 15, in <module>
        class person(object, metaclass=Foo):
      File "E:/***/***/***/test1.py", line 11, in __init__
        raise TypeError("请加上注释")
    TypeError: 请加上注释
    

    因为我们在Foo类的__init__方法中对创建类的条件做了一些逻辑处理(如果类中没有注释,直接抛异常),解决的办法:第九行加上注释即可

    class  Foo(type):
        def __init__(self,class_name,class_bases,class_dict):
            if not class_dict.get("__doc__"):
                raise  TypeError("请加上注释")
            super().__init__(class_name,class_bases,class_dict)
    
    
    class person(object,metaclass=Foo):
        '''我加上注释了'''
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def run(self):
            print("run")
    
        def eat(self):
            print("eat")
    

    总结:元类创建类,主要__init__方法中增加逻辑

    造对象

    NAME = 'PLF'
    AGE = 18
    class Foo(type):
        def __init__(self,class_name,class_bases,class_dict):
            self.count = 1
            super().__init__(class_name,class_bases,class_dict)
    
        def __call__(self, *args, **kwargs):
            # 造空类
            obj = object.__new__(self)
            # 造对象
            if  len(args) == 0 and len(kwargs) == 0:
                self.__init__(obj,NAME,AGE)
                return obj
            self.__init__(obj,*args,**kwargs)
            return  obj
    
    class Person(object,metaclass=Foo):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def run(self):
            print("run")
    
        def eat(self):
            print("eat")
    
        def __call__(self, *args, **kwargs):
            print("调用了")
            # return self
    
    one = Person('zhangsan',1000)
    print('one对象的name:',one.name)
    print('one对象的age:',one.age)
    
    ori = Person()
    print('ori对象的name:',ori.name)
    print('ori对象的name:',ori.age)
    
    one对象的name: zhangsan
    one对象的age: 1000
    ori对象的name: PLF
    ori对象的name: 18
    

    总结:通过元类造对象,操作的逻辑可以在__call__方法或者__new__方法中进行

  • 相关阅读:
    K好数
    蓝桥杯 安慰奶牛
    蓝桥杯 节点选择
    模拟链表
    10588
    八数码的 八种境界
    HIT 2051
    概率DP
    数组越界溢出
    FATFS在SD卡里,写入多行数据出的问题
  • 原文地址:https://www.cnblogs.com/plf-Jack/p/11066400.html
Copyright © 2011-2022 走看看