16 元类
2018-06-18 02:39:26来源:未知 阅读 ()
面向对象学习目录
1 面向对象介绍
2 类、实例、属性、方法详解
3 面向过程与面向对象进一步比较
4 类与对象
5 属性查找与绑定方法
6 小结
7 继承与派生
8 组合
9 抽象类
10 多态
11 封装
12 绑定方法与非绑定方法
13 内置方法(上)
14 内置方法(中)之描述符
15 内置方法(下)
16 元类
一 知识储备
1 #可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中 2 g={'x':1,'y':2} 3 l={} 4 5 exec(''' 6 global x,z 7 x=100 8 z=200 9 10 m=300 11 ''',g,l) 12 13 print(g) #{'x': 100, 'y': 2,'z':200,......} 14 print(l) #{'m': 300}
二 引子(类也是对象)
1 class Foo: 2 pass 3 4 f1=Foo() #f1是通过Foo类实例化的对象
1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的 2 print(type(f1)) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建 3 print(type(Foo)) # 输出:<type 'type'>
三 什么是元类?
四 创建类的两种方式
1 class Chinese(object): 2 country='China' 3 def __init__(self,name,age): 4 self.name=name 5 self.age=age 6 def talk(self): 7 print('%s is talking' %self.name)
1 #准备工作: 2 3 #创建类主要分为三部分 4 5 1 类名 6 7 2 类的父类 8 9 3 类体 10 11 12 #类名 13 class_name='Chinese' 14 #类的父类 15 class_bases=(object,) 16 #类体 17 class_body=""" 18 country='China' 19 def __init__(self,name,age): 20 self.name=name 21 self.age=age 22 def talk(self): 23 print('%s is talking' %self.name) 24 """
1 class_dic={} 2 exec(class_body,globals(),class_dic) 3 4 5 print(class_dic) 6 #{'country': 'China', 'talk': <function talk at 0x101a560c8>, '__init__': <function __init__ at 0x101a56668>}
1 Foo=type(class_name,class_bases,class_dic) #实例化type得到对象Foo,即我们用class定义的类Foo 2 3 4 print(Foo) 5 print(type(Foo)) 6 print(isinstance(Foo,type)) 7 ''' 8 <class '__main__.Chinese'> 9 <class 'type'> 10 True 11 '''
- 第 1 个参数是字符串 ‘Foo’,表示类名
- 第 2 个参数是元组 (object, ),表示所有的父类
- 第 3 个参数是字典,这里是一个空字典,表示没有定义的属性和方法
五 自定义元类控制类的行为
#知识储备: #产生的新对象 = object.__new__(继承object类的子类) #步骤一:如果说People=type(类名,类的父类们,类的名称空间),那么我们定义元类如下,来控制类的创建 class Mymeta(type): # 继承默认元类的一堆属性 def __init__(self, class_name, class_bases, class_dic): if '__doc__' not in class_dic or not class_dic.get('__doc__').strip(): raise TypeError('必须为类指定文档注释') if not class_name.istitle(): raise TypeError('类名首字母必须大写') super(Mymeta, self).__init__(class_name, class_bases, class_dic) class People(object, metaclass=Mymeta): country = 'China' def __init__(self, name, age): self.name = name self.age = age def talk(self): print('%s is talking' % self.name) #步骤二:如果我们想控制类实例化的行为,那么需要先储备知识__call__方法的使用 class People(object,metaclass=type): def __init__(self,name,age): self.name=name self.age=age def __call__(self, *args, **kwargs): print(self,args,kwargs) # 调用类People,并不会出发__call__ obj=People('egon',18) # 调用对象obj(1,2,3,a=1,b=2,c=3),才会出发对象的绑定方法obj.__call__(1,2,3,a=1,b=2,c=3) obj(1,2,3,a=1,b=2,c=3) #打印:<__main__.People object at 0x10076dd30> (1, 2, 3) {'a': 1, 'b': 2, 'c': 3} #总结:如果说类People是元类type的实例,那么在元类type内肯定也有一个__call__,会在调用People('egon',18)时触发执行,然后返回一个初始化好了的对象obj #步骤三:自定义元类,控制类的调用(即实例化)的过程 class Mymeta(type): #继承默认元类的一堆属性 def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名首字母必须大写') super(Mymeta,self).__init__(class_name,class_bases,class_dic) def __call__(self, *args, **kwargs): #self=People print(self,args,kwargs) #<class '__main__.People'> ('egon', 18) {} #1、实例化People,产生空对象obj obj=object.__new__(self) #2、调用People下的函数__init__,初始化obj self.__init__(obj,*args,**kwargs) #3、返回初始化好了的obj return obj class People(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking' %self.name) obj=People('egon',18) print(obj.__dict__) #{'name': 'egon', 'age': 18} #步骤四: class Mymeta(type): #继承默认元类的一堆属性 def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名首字母必须大写') super(Mymeta,self).__init__(class_name,class_bases,class_dic) def __call__(self, *args, **kwargs): #self=People print(self,args,kwargs) #<class '__main__.People'> ('egon', 18) {} #1、调用self,即People下的函数__new__,在该函数内完成:1、产生空对象obj 2、初始化 3、返回obj obj=self.__new__(self,*args,**kwargs) #2、一定记得返回obj,因为实例化People(...)取得就是__call__的返回值 return obj class People(object,metaclass=Mymeta): country='China' def __init__(self,name,age): self.name=name self.age=age def talk(self): print('%s is talking' %self.name) def __new__(cls, *args, **kwargs): obj=object.__new__(cls) cls.__init__(obj,*args,**kwargs) return obj obj=People('egon',18) print(obj.__dict__) #{'name': 'egon', 'age': 18} #步骤五:基于元类实现单例模式,比如数据库对象,实例化时参数都一样,就没必要重复产生对象,浪费内存 class Mysql: __instance=None def __init__(self,host='127.0.0.1',port='3306'): self.host=host self.port=port @classmethod def singleton(cls,*args,**kwargs): if not cls.__instance: cls.__instance=cls(*args,**kwargs) return cls.__instance obj1=Mysql() obj2=Mysql() print(obj1 is obj2) #False obj3=Mysql.singleton() obj4=Mysql.singleton() print(obj3 is obj4) #True #应用:定制元类实现单例模式 class Mymeta(type): def __init__(self,name,bases,dic): #定义类Mysql时就触发 self.__instance=None super().__init__(name,bases,dic) def __call__(self, *args, **kwargs): #Mysql(...)时触发 if not self.__instance: self.__instance=object.__new__(self) #产生对象 self.__init__(self.__instance,*args,**kwargs) #初始化对象 #上述两步可以合成下面一步 # self.__instance=super().__call__(*args,**kwargs) return self.__instance class Mysql(metaclass=Mymeta): def __init__(self,host='127.0.0.1',port='3306'): self.host=host self.port=port obj1=Mysql() obj2=Mysql() print(obj1 is obj2)
六 练习题
1 class Mymetaclass(type): 2 def __new__(cls,name,bases,attrs): 3 update_attrs={} 4 for k,v in attrs.items(): 5 if not callable(v) and not k.startswith('__'): 6 update_attrs[k.upper()]=v 7 else: 8 update_attrs[k]=v 9 return type.__new__(cls,name,bases,update_attrs) 10 11 class Chinese(metaclass=Mymetaclass): 12 country='China' 13 tag='Legend of the Dragon' #龙的传人 14 def walk(self): 15 print('%s is walking' %self.name) 16 17 18 print(Chinese.__dict__) 19 ''' 20 {'__module__': '__main__', 21 'COUNTRY': 'China', 22 'TAG': 'Legend of the Dragon', 23 'walk': <function Chinese.walk at 0x0000000001E7B950>, 24 '__dict__': <attribute '__dict__' of 'Chinese' objects>, 25 '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, 26 '__doc__': None} 27 '''
1 class Mymetaclass(type): 2 # def __new__(cls,name,bases,attrs): 3 # update_attrs={} 4 # for k,v in attrs.items(): 5 # if not callable(v) and not k.startswith('__'): 6 # update_attrs[k.upper()]=v 7 # else: 8 # update_attrs[k]=v 9 # return type.__new__(cls,name,bases,update_attrs) 10 11 def __call__(self, *args, **kwargs): 12 if args: 13 raise TypeError('must use keyword argument for key function') 14 obj = object.__new__(self) #创建对象,self为类Foo 15 16 for k,v in kwargs.items(): 17 obj.__dict__[k.upper()]=v 18 return obj 19 20 class Chinese(metaclass=Mymetaclass): 21 country='China' 22 tag='Legend of the Dragon' #龙的传人 23 def walk(self): 24 print('%s is walking' %self.name) 25 26 27 p=Chinese(name='egon',age=18,sex='male') 28 print(p.__dict__)
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:python实现购物简单流程
下一篇:python3安装过程
- Python之对象持久化笔记 2019-08-13
- python之函数、面向对象 2019-08-13
- Python-19-元类 2019-07-24
- Python的面向对象2 2019-07-24
- Python之路【第九篇】:Python面向对象 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash