zoukankan      html  css  js  c++  java
  • python 元类以及练习

    '''
    # 知识储备exec()
    # 参数1:字符串形式的命令
    # 参数2:全局作用域(字典形式),如果不指定默认就使用globals()
    # 参数3:局部作用域(字典形式),如果不指定默认就使用locals()
    '''
    # g = {
    #     'x': 2,
    #     'y': 4
    # }
    # l = {}
    # exec('''
    # global x, m
    # x = 10
    # m = 100
    #
    # z = 3
    # ''', g, l)
    # print(g)
    # print(l)
    '''一切皆对象,元类(产生类的类叫元类,默认用class定义的类,他们的元类是type)'''
    # 一切皆对象,对象可以怎么用?
    # 1.都可以被引用,x = obj
    # 2.都可以当做函数的参数传入
    # 3.都可以当作函数的返回值
    # 4.都可以当做容器类型的元素,l = [func, time, obj, l]
    
    # # 类也是对象,Foo = type(...)
    # class Foo:
    #     pass
    # obj = Foo()
    # print(type(obj))
    # print(type(Foo))
    # #产生类的类叫元类,默认用class定义的类,他们的元类是type
    '''定义类'''
    # 方式一class
    # class Chinese:
    #     country = 'china'
    #     def __init__(self, name):
    #         self.name = name
    #     def talk(self):
    #         print('%s is talking' % self.name)
    # print(Chinese)
    # 方式二type
    #定义类三要素 类名,类的基类, 类的名称空间
    # class_name = 'Chinese'
    # class_bases = (object,)
    # class_body = '''
    # country = 'china'
    # def __init__(self, name):
    #     self.name = name
    # def talk(self):
    #     print('%s is talking' % self.name)
    # '''
    # class_dic = {}
    # exec(class_body, globals(), class_dic)
    # # print(class_dic)
    #
    # Chinese1 = type(class_name, class_bases, class_dic)
    # print(Chinese1)
    '''自定义元类控制类的创建'''
    # class Mymeta(type):
    #     def __init__(self, class_name, class_bases, class_dic):
    #         if not class_name.istitle():
    #             raise TypeError('类名首字母必须大写')
    #         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    #             raise TypeError('必须有注释,且注释不能为空')
    #         super(Mymeta, self).__init__(class_name, class_bases, class_dic)
    # class Chinese(object, metaclass = Mymeta):
    #     '''
    #     国人
    #     '''
    #     country = 'china'
    #     def __init__(self, name):
    #         self.name = name
    #     def talk(self):
    #         print('%s is talking' % self.name)
    # c = Chinese('name')
    # # Chinese = type(class_name, class_bases, class_dic)
    '''知识储备__call__方法'''
    # class Foo:
    #     def __call__(self, *args, **kwargs):
    #         print(self)
    #         print(args)
    #         print(kwargs)
    # obj = Foo()
    # obj(1, 2, 3, a=1, b=2, c=3)
    
    # 元类内部也应该有一个__call__方法,会在调用Foo时触发执行
    '''自定义元类控制类的实例化行为'''
    # class Mymeta(type):
    #     def __init__(self, class_name, class_bases, class_dic):
    #         if not class_name.istitle():
    #             raise TypeError('类名首字母必须大写')
    #         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    #             raise TypeError('必须有注释,且注释不能为空')
    #         super(Mymeta, self).__init__(class_name, class_bases, class_dic)
    #     def __call__(self, *args, **kwargs):
    #         # print(self)
    #         # print(args)
    #         # print(kwargs)
    #         # 第一件事,造一个空对象
    #         obj = object.__new__(self)
    #         # 第二件事,初始化
    #         self.__init__(obj, *args, **kwargs)
    #         # 第三件事,返回obj
    #         return obj
    # class Chinese(object, metaclass = Mymeta):
    #     '''
    #     国人
    #     '''
    #     country = 'china'
    #     def __init__(self, name):
    #         self.name = name
    #     def talk(self):
    #         print('%s is talking' % self.name)
    # obj = Chinese('xander')  # Chinese.__call__(Chinese, 'xander')
    # print(obj.__dict__)
    '''自定义元类控制类的实例化行为的应用'''
    # 单例模式
    
    # 实现方式一:
    # class MySQL:
    #     __instance = None
    #
    #     def __init__(self):
    #         self.host = '127.0.0.1'
    #         self.port = 3306
    #     @classmethod
    #     def singleton(cls):
    #         if not cls.__instance:
    #             obj = cls()
    #             cls.__instance = obj
    #         return cls.__instance
    # # obj1 = MySQL()
    # # obj2 = MySQL()
    # # print(obj1)
    # # print(obj2)
    # obj1 = MySQL.singleton()
    # obj2 = MySQL.singleton()
    # print(obj1 is obj2)
    
    # 实现方式二:元类的方式
    class Mymeta(type):
        def __init__(self, class_name, class_bases, class_dic):
            if not class_name.istitle():
                raise TypeError('类名首字母必须大写')
            if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
                raise TypeError('必须有注释,且注释不能为空')
            super(Mymeta, self).__init__(class_name, class_bases, class_dic)
            self.__instance = None
        def __call__(self, *args, **kwargs):
            if not self.__instance:
                obj = object.__new__(self)
                self.__init__(obj)
                self.__instance = obj
            return self.__instance
    class Mysql(object, metaclass=Mymeta):
        '''单例模式'''
        def __init__(self):
            self.host = '127.0.0.1'
            self.port = 3306
        @classmethod
        def singleton(cls):
            if not cls.__instance:
                obj = cls()
                cls.__instance = obj
            return cls.__instance
    obj1 = Mysql()
    obj2 = Mysql()
    print(obj1 is obj2)

    练习

    # 练习一:在元类中控制把自定义类的数据属性都变成大写
    class Mymate(type):
        def __new__(cls, name, args, kwargs):
            obj = {}
            print(name)
            print(args)
            print(kwargs)
            for a, b in kwargs.items():
                if not a.startswith('__'):
                    obj[a.upper()] = b
                else:
                    obj[a] = b
            return type.__new__(cls, name, args, obj)
    class Chinese(object, metaclass=Mymate):
        country = 'chinese'
        def talk(self):
            print('is talking')
    print(Chinese.__dict__)
    
    # 练习二:在元类中控制自定义的类无需init方法
    # 1.元类帮其完成创建对象,以及初始化操作;
    # 2.要求实例化时传参必须为关键字形式,否则抛出异常TypeError: must use keyword argument
    # 3.key作为用户自定义类产生对象的属性,且所有属性变成大写
    class Mymate(type):
        def __call__(self, *args, **kwargs):
            if args:
                raise TypeError(':must use keyword argument')
            obj = object.__new__(self)  #创建对象,self为类Chinese
    
            for k, v in kwargs.items():
                obj.__dict__[k.upper()] = v
            return obj
    
    class Chinese(object, metaclass=Mymate):
        country = 'chinese'
        def talk(self):
            print('is talking')
    p = Chinese(name='egon', age=18, sex='male')
    print(p.__dict__)
  • 相关阅读:
    剑指offer(14)链表中倒数第K个节点
    剑指offer(13)调整数组顺序使奇数位于偶数前面
    跨域资源共享CORS
    同源政策
    剑指offer(12)数值的整数次方
    剑指offer(11)二进制中1的个数
    面试金典——交点
    LeetCode——简化路径
    LeetCode——跳跃游戏 I-II
    LeetCode——最大矩形
  • 原文地址:https://www.cnblogs.com/Xanderzyl/p/10666037.html
Copyright © 2011-2022 走看看