python核心高级学习总结6------面向对象进阶之元类
2017-07-22 12:52
513 查看
元类引入
在多数语言中,类就是一组用来描述如何生成对象的代码段,在python中同样如此,但是在python中把类也称为类对象,是的,你没听错,在这里你只要使用class关键字定义了类,其解释器在执行时就会创建一个对象,但是这个对象比较特殊,它可以创建自己的实例对象(像其他语言一样)。你可以对它进行下面的操作:1. 你可以将它赋值给⼀个变量
2. 你可以拷⻉它
3. 你可以为它增加属性
4. 你可以将它作为函数参数进⾏传递
动态创建类
听起来python在这方面跟一些语言的差别了吧,没错它还可以在运行时动态地创建它们,你可以在函数中创建类,用class关键字即可。def choose_class(name): if name == 'foo': class Foo(object): pass return Foo # 返回的是类, 不是类的实例 else: class Bar(object): pass return Bar
如果你想知道python中的变量或者数值的类型,你可以用万能而强大的type,如下(注意它们的返回值)
>>> print type(1) #数值的类型 <type 'int'> >>> print type("1") #字符串的类型 <type 'str'> >>> print type(ObjectCreator()) #实例对象的类型 <class '__main__.ObjectCreator'> >>> print type(ObjectCreator) #类的类型 <type 'type'>
使用type创建类
创建格式:type(类名, 由⽗类名称组成的元组( 针对继承的情况, 可以为空) ,包含属性的字典( 名称和值) )可以⼿动像这样创建:
Test2 = type("Test2",(),{}) #定了⼀个Test2类 In [5]: Test2() #创建了⼀个Test2类的实例对象 Out[5]: <__main__.Test2 at 0x10d406b38>上面等价于
class Test2: pass
使⽤type创建带有属性的类
Foo = type('Foo', (), {'bar':True})可以翻译为
>>> class Foo(object): … bar = True这个类跟普通创建的类一样使用,如继承这个类,你可以用下面的方法
>>> FooChild = type('FooChild', (Foo,),{}) >>> print FooChild <class '__main__.FooChild'> >>> print FooChild.bar # bar属性是由Foo继承⽽来 True同样等价于
>>> class FooChild(Foo): … pass注意:添加的属性都是类属性,第二个参数是继承自哪儿,采用元组的形式,也要知道在python中元组中只有一个参数表示方法只能是(xx,),而不能是(xx)
使⽤type创建带有⽅法的类
如果你想为你的类增加方法,那么你创建一个签名函数,然后添加其为属性赋值即可。添加实例方法
In [46]: def echo_bar(self): #定义了⼀个普通的函数 ...: print(self.bar) ...: In [47]: FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar}) In [48]: hasattr(Foo, 'echo_bar') #判断Foo类中, 是否有echo_bar这个属性 Out[48]: False In [49]: In [49]: hasattr(FooChild, 'echo_bar') #判断FooChild类中, 是否有echo_bar这个 Out[49]: True In [50]: my_foo = FooChild() In [51]: my_foo.echo_bar() True
添加类方法
In [42]: @classmethod ...: def testClass(cls): ...: print(cls.bar) ...: In [43]: In [43]: Foochild = type('Foochild', (Foo,), {"echo_bar":echo_bar,"testClass":testClass}) In [44]: In [44]: fooclid = Foochild() In [45]: fooclid.testClass() True
添加静态方法
In [36]: @staticmethod ...: def testStatic(): ...: print("static method ....") ...: In [37]: Foochild = type('Foochild', (Foo,), {"echo_bar":echo_bar,“testStatic”:testStatic}) In [38]: fooclid = Foochild() In [39]: fooclid.testStatic Out[39]: <function __main__.testStatic> In [40]: fooclid.testStatic() static method .... In [41]: fooclid.echo_bar() True看到这么多实现动态类的方法,你该明白python是怎么做到的,在这里就涉及到元类,元类就是用来创建类的东西,而创建类就是为了创建类的实例对象,所以可以这样理解,元类就是为了创建类对象的,而type实际上就是一个元类,传统类的元类就是types.classType,在python中元类的介绍中也介绍了元类,有兴趣的读者可以去看看。
SO,结论就是Python中所有的东⻄, 注意, 我是指所有的东⻄——都是对象。 这包括整数、 字符串、 函数以及类。 它们全部都是对象,⽽且它们都是从⼀个类创建⽽来, 这个类就是type。
__metaclass__属性
你也可以定义自己的元类,用到的就是上面的属性,首先,你可以在定义⼀个类的时候为其添加__metaclass__属性。class Foo(object): __metaclass__ = something… #...省略...那么当python解释器看到下面代码时
class Foo(Bar): passpython做了如下的操作:
1. Foo中有__metaclass__这个属性吗? 如果是, Python会通过__metaclass__创建⼀个名字为Foo的类(对象)
2. 如果Python没有找到__metaclass__, 它会继续在Bar( ⽗类) 中寻找__metaclass__属性, 并尝试做和前⾯同样的操作。
3. 如果Python在任何⽗类中都找不到__metaclass__, 它就会在模块层次中去寻找__metaclass__, 并尝试做同样的操作。
4. 如果还是找不到__metaclass__,Python就会⽤内置的type来创建这个类对象。
在这个__metaclass__中可以放一些什么代码呢?------可以做任何涉及到类操作的事情,用type或者其子类来完成。
下面是用自定义类来当做元类
#coding=utf-8 class UpperAttrMetaClass(type): # __new__ 是在__init__之前被调⽤的特殊⽅法 # __new__是⽤来创建对象并返回之的⽅法 # ⽽__init__只是⽤来将传⼊的参数初始化给对象 # 你很少⽤到__new__, 除⾮你希望能够控制对象的创建 # 这⾥, 创建的对象是类, 我们希望能够⾃定义它, 所以我们这⾥改写__new__ # 如果你希望的话, 你也可以在__init__中做些事情 # 还有⼀些⾼级的⽤法会涉及到改写__call__特殊⽅法, 但是我们这⾥不⽤ def __new__(cls, future_class_name, future_class_parents, future_clas #遍历属性字典, 把不是__开头的属性名字变为⼤写 newAttr = {} for name,value in future_class_attr.items(): if not name.startswith("__"): newAttr[name.upper()] = value # ⽅法1: 通过'type'来做类对象的创建 # return type(future_class_name, future_class_ parents, newAttr) # ⽅法2: 复⽤type.__new__⽅法 # 这就是基本的OOP编程, 没什么魔法 # return type.__new__(cls, future_class_name, future_class_parent # ⽅法3: 使⽤super⽅法 return super(UpperAttrMetaClass, cls).__new__(cls, future_class_n #python2的⽤法 class Foo(object): __metaclass__ = UpperAttrMetaClass bar = 'bip' # python3的⽤法 # class Foo(object, metaclass = UpperAttrMetaClass): # bar = 'bip' print(hasattr(Foo, 'bar')) # 输出: False print(hasattr(Foo, 'BAR')) # 输出:True
f = Foo() print(f.BAR) # 输出:'bip'
其实简单地来讲,python中的元类用处一般就是下面三个
1. 拦截类的创建
2. 修改类
3. 返回修改之后的类
哈哈,我想说的是对于元类咱们99%的人不会用到。
相关文章推荐
- python学习-面向对象进阶之元类(三)
- python核心高级学习总结2----------pdb的调试
- python核心高级学习总结4-------python实现进程通信
- python核心高级学习总结5--------python实现线程
- python核心高级学习总结1---------*args和**kwargs
- python核心高级学习总结7---------正则表达式
- python核心高级学习总结8------动态性、__slots__、生成器、迭代器、装饰、闭包
- python入门、进阶、高级阶段学习安排
- 【Python】[面向对象的高级编程] 元类 ---听说这个很难理解
- Python面向对象进阶之高级编程
- 学习Python就业有哪些方向?附加视频教程(python3从入门到进阶(面向对象),实战(爬虫,飞机游戏,GUI)视频教程)
- python学习-面向对象进阶之闭包(八)
- Eclipse插件开发 学习笔记 PDF 第一篇到第四篇 免分下载 开发基础 核心技术 高级进阶 综合实例
- 【PHP进阶篇】3.类与面向对象--慕课网【学习总结】
- python3进阶学习总结——模拟登录
- python学习笔记1:面向对象的高级特性1__slots__
- Python学习总结(二)——面向对象
- python学习-面向对象进阶之python是动态语言(四)
- python学习-面向对象进阶之迭代器(九)
- Python学习记录_Day015(周总结)面向对象进阶篇