【python进阶】详解元类及其应用1
前言
元类在python中是很重要的一部分,我将分两次去讲解元类及其应用,此篇为详解元类及其应用第一篇,下面开始今天的说明~~~
1. 类也是对象
在⼤多数编程语⾔中,类就是⼀组⽤来描述如何⽣成⼀个对象的代码段。在 Python中这⼀点仍然成⽴:
>>> class ObjectCreator(object): … pass … >>>my_object = ObjectCreator() >>>print(my_object) <__main__.ObjectCreator object at 0x8974f2c>
但是,Python中的类还远不⽌如此。类同样也是⼀种对象。是的,没错,就是对象。只要你使⽤关键字class,Python解释器在执⾏的时候就会创建⼀个 对象。
下⾯的代码段:
>>> class ObjectCreator(object): ... pass ...
将在内存中创建⼀个对象,名字就是ObjectCreator。这个对象(类对象 ObjectCreator)拥有创建对象(实例对象)的能⼒。但是,它的本质仍然是 ⼀个对象,于是乎你可以对它做如下的操作:
1. 你可以将它赋值给⼀个变量
2. 你可以拷⻉它
3. 你可以为它增加属性
4. 你可以将它作为函数参数进⾏传递
下⾯是示例:
>>> print(ObjectCreator)#你可以打印⼀个类,因为它其实也是⼀个对象 <class '__main__.ObjectCreator'> >>> def echo(o): ... print(o) ... >>> echo(ObjectCreator)#你可以将类做为参数传给函数 <class '__main__.ObjectCreator'> >>> print(hasattr(ObjectCreator,'new_attribute')) False >>>ObjectCreator.new_attribute='foo'#你可以为类增加属性 >>>print(hasattr(ObjectCreator, 'new_attribute')) True >>>print(ObjectCreator.new_attribute) foo >>>ObjectCreatorMirror=ObjectCreator#你可以将类赋值给⼀个变量 >>>print(ObjectCreatorMirror()) <__main__.ObjectCreator object at 0x8997b4c>
2. 动态地创建类
因为类也是对象,你可以在运⾏时动态的创建它们,就像其他任何对象⼀样。⾸先,你可以在函数中创建类,使⽤class关键字即可。
>>> def choose_class(name): ...: if name == 'foo': ...: class Foo(object): ...: pass ...: return Foo #返回的是类,不是类的实例 ...: else: ...: class Bar(object): ...: pass ...: return Bar ...: >>> MyClass=choose_class('foo') >>> print(MyClass)#函数返回的是类,不是类的实例 <class '__main__.choose_class.<locals>.Foo'> >>> print(MyClass())#你可以通过这个类创建类实例,也就是对象 <__main__.choose_class.<locals>.Foo object at 0x000001C54F7007B8>
但这还不够动态,因为你仍然需要⾃⼰编写整个类的代码。由于类也是对 象,所以它们必须是通过什么东⻄来⽣成的才对。当你使⽤class关键字时, Python解释器⾃动创建这个对象。但就和Python中的⼤多数事情⼀样, Python仍然提供给你⼿动处理的⽅法。
还记得内建函数type吗?这个古⽼但强⼤的函数能够让你知道⼀个对象的类 型是什么,就像这样:
>>> print(type(1))#数值的类型 <class 'int'> >>> print(type("1"))#字符串的类型 <class 'str'> >>> print(type(ObjectCreator()))#实例对象的类型 <class '__main__.ObjectCreator'> >>> print(type(ObjectCreator))#类的类型 <type 'type'>
仔细观察上⾯的运⾏结果,发现使⽤type对ObjectCreator查看类型是,答案 为type, 是不是有些惊讶。。。看下⾯
3. 使⽤type创建类
type还有⼀种完全不同的功能,动态的创建类。
type可以接受⼀个类的描述作为参数,然后返回⼀个类。(要知道,根据传入参数的不同,同⼀个函数拥有两种完全不同的⽤法是⼀件很傻的事情,但 这在Python中是为了保持向后兼容性)
type可以像这样⼯作:
type(类名, 由⽗类名称组成的元组(针对继承的情况,可以为空),包含属 性的字典(名称和值))
⽐如下⾯的代码:
In [7]: class Test:#定义了⼀个Test类 ...: pass ...: In [8]: Test()#创建了⼀个Test类的实例对象 Out[8]: <__main__.Test at 0x1c54f648518>
可以⼿动像这样创建:
In [9]: Test2 = type("Test2",(),{})#定义了⼀个Test2类 In [10]: Test2()#创建了⼀个Test2类的实例对象 Out[10]: <__main__.Test2 at 0x1c54f66ed68>
我们使⽤"Test2"作为类名,并且也可以把它当做⼀个变量来作为类的引⽤。 类和变量是不同的,这⾥没有任何理由把事情弄的复杂。即type函数中第1个实参,也可以叫做其他的名字,这个名字表示类的名字
In [11]: MyDogClass = type('MyDog',(),{}) In [12]: print(MyDogClass) <class '__main__.MyDog'>
使⽤help来测试这2个类
In [13]: help(Test)#⽤help查看Test类 Help on class Test in module __main__: class Test(builtins.object) | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
In [14]: help(Test2)#⽤help查看Test2类 Help on class Test2 in module __main__: class Test2(builtins.object) | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
4.使⽤type创建带有属性的类
type 接受⼀个字典来为类定义属性,因此
In [15]: Foo = type('Foo',(),{'bar':True})
可以翻译为:
In [16]: class Foo(object): ...: bar = True
并且可以将Foo当成⼀个普通的类⼀样使⽤:
In [17]: print(Foo) <class '__main__.Foo'> In [18]: print(Foo.bar) True In [19]: f = Foo() In [20]: print(f) <__main__.Foo object at 0x000001C54F6511D0> In [21]: print(f.bar) True
当然,你可以向这个类继承,所以,如下的代码:
In [22]: class FooChild(Foo): ...: pass
就可以写成:
In [23]: FooChild = type('FooChild',(Foo,),{}) In [24]: print(FooChild) <class '__main__.FooChild'> In [25]: print(FooChild.bar) True
注意:
- type的第2个参数,元组中是⽗类的名字,⽽不是字符串
-
添加的属性是类属性,并不是实例属性
作 者:Angel_Kitty
出 处:https://www.cnblogs.com/ECJTUACM-873284962/
关于作者:阿里云ACE,目前主要研究方向是Web安全漏洞以及反序列化。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
欢迎大家关注我的微信公众号IT老实人(IThonest),如果您觉得文章对您有很大的帮助,您可以考虑赏博主一杯咖啡以资鼓励,您的肯定将是我最大的动力。thx.
我的公众号是IT老实人(IThonest),一个有故事的公众号,欢迎大家来这里讨论,共同进步,不断学习才能不断进步。扫下面的二维码或者收藏下面的二维码关注吧(长按下面的二维码图片、并选择识别图中的二维码),个人QQ和微信的二维码也已给出,扫描下面👇的二维码一起来讨论吧!!!
欢迎大家关注我的Github,一些文章的备份和平常做的一些项目会存放在这里。