博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 元类以及练习
阅读量:5377 次
发布时间:2019-06-15

本文共 5453 字,大约阅读时间需要 18 分钟。

'''# 知识储备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.__instanceclass 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.__instanceobj1 = 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 objclass Chinese(object, metaclass=Mymate):    country = 'chinese'    def talk(self):        print('is talking')p = Chinese(name='egon', age=18, sex='male')print(p.__dict__)

 

转载于:https://www.cnblogs.com/Xanderzyl/p/10666037.html

你可能感兴趣的文章
[HDU 3652] B-number
查看>>
详解主席树(可持久化线段树)
查看>>
php 根据给定的年份和月份获取该年份该月份的起始和结束时间
查看>>
用C#实现的条形码和二维码编码解码器
查看>>
DFA与动态规划
查看>>
多线程:简易版本生产消费者模式纯语言概述
查看>>
自动生成 顺序图(序列图) 软件
查看>>
大问题小bug
查看>>
【皇甫】☀那些数据源...
查看>>
FastReport.Net使用:[6]HTML标签使用
查看>>
prime number
查看>>
处理字符串的一些js/jq方法(去除HTML,去除空格,计算真实长度,截取中英文字符)...
查看>>
淘宝分类导航条;纯css实现固定导航栏
查看>>
分布的拟合和检验
查看>>
Project Euler:Problem 42 Coded triangle numbers
查看>>
2014acm亚洲区域赛陕西赛总结
查看>>
内网渗透之域环境搭建
查看>>
server2012 配置SSL证书
查看>>
面试题40 数组中只出现一次的数字
查看>>
开发HTML5手机游戏的5个注意要点--手机开发前景-- 转
查看>>