资讯专栏INFORMATION COLUMN

Python实例一个类背后发生了什么

shusen / 527人阅读

摘要:好吧,事实上,类本身也是实例,当然,它们是元类的实例。中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了。

写在最前面

一些很重要的知识,我的写得有点乱,也可以去看这些文章

Python 面向对象(初级篇)

Python 面向对象(进阶篇)

深刻理解Python中的元类(metaclass)

首先来看一个例子,正常情况下我们定义并且实例一个类如下

class Foo(object):
 
    def __init__(self):
        pass
 
obj = Foo()   # obj是通过Foo类实例化的对象

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。

print type(obj) # 输出: Foo 表示,obj 对象由Foo类创建
print type(Foo) # 输出:type表示,Foo类对象由 type 类创建

如果按照一切事物都是对象的理论:对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

两个基本的类

这里和有必要提到一下在Python中有两个最基本的对象,,这两个对象是所有对象的起源。

的类型是(它本身),的父类是

的类型是没有父类

在Python对象系统中,的关系就像鸡和蛋的关系,不能说谁先于(创建)谁,两者是相互依赖的,共同构成了Python对象系统的基础.有点难理解,不过没有关系,知道有种这么两个东西就好了,比较我们也不是设计Python的人,没有必要搞的那么清楚.

类的创建

主要有两种方式,不过本质上都是一样的,都是通过type类来实例一个用户类

普通方式
Python
1    class Foo(object):
2     
3        def func(self):
4            print "hello "

特殊方式(type类的构造函数)
Python
1    def func(self):
2        print "hello "
3     
4    Foo = type("Foo",(object,), {"func": func})
5    #type第一个参数:类名
6    #type第二个参数:当前类的基类
7    #type第三个参数:类的成员

由上面可以看出来 , Foo类是由type类实例而来,那么具体的创建的过程是怎么样的呢,接着往下面看:

来了解几个概念

new 和 __init()和__metaclass__:

__new__函数是实例一个类所要调用的函数,每当我们调用obj = Foo()来实例一个类时,都是先调用__new__()

然后再调用__init__()函数初始化实例. __init__()在__new__()执行后执行,

类中还有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

阐述运行过程

mytype产生一个叫做Foo的实例,主要的原理就是设置了,__metaclass__=MyTypoe,这样就指定mytype类来实例foo类,如果Python没有找到__metaclass__,它会继续在(父类)中寻找 __metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。

mytype类中的__new__方法返回了一个对象,所有的Python实例都是这句代码创建的type.__new__(cls,name,bases,attrs)

mytype的__init__()函数初始化Foo类,在这里我们可以和在__new__()函数一样设置Foo类的attr属性,比如类中的方法,字段属性等

和Foo类的创建过程一样,studen类继承了Foo类,所以重复123步骤,得到一个studen类

当用户使用Foo()或者studen()来实例类时,会默认调用类中的_new_()方法,要是之类里面没有这个方法就到父类里面寻找__new__(),我们可以充分利用这个new函数,比如来实现Python中的单例模式,或者对类成员进行批量的修改等等.

产生了一个实例后马上执行__init__()函数,进行初始化实例,

由上面的运行结果可以看出,其中Foo和studen类的类型是,这也证明了Foo类和studen类都是由MyType实例而来…而第三个例子,可以看出Foo2类的类型是,这个并不例外,Foo2继承了object类,(这个,还是跳过吧,前面已经讲过type和object相爱相杀的关系了)

总结

首先,你知道了类其实是能够创建出类实例的对象。好吧,事实上,类本身也是实例,当然,它们是元类的实例。Python中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了type。type实际上是它自己的元类,在纯Python环境中这可不是你能够做到的,这是通过在实现层面耍一些小手段做到的。其次,元类是很复杂的。对于非常简单的类,你可能不希望通过使用元类来对类做修改。你可以通过其他两种技术来修改类:

Monkey patching

class decora

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37754.html

相关文章

  • 流畅的python读书笔记-第三章Python 字典与集合

    摘要:小总结标准库里的所有映射类型都是利用来实现只有可散列的数据类型才能用作这些映射里的键值不用字典推导用处理找不到的键找不到键返回某种默认值底层是与调用实现的字典插入更新原理其他大多数映射类型都提供了两个很强大的方法和。 字典和集合 标准库里的所有映射类型都是利用 dict 来实现的只有可散列的数据类型才能用作这些映射里的键(值不用) 可散列 一个对象是可散列的 它的散列值是不变的 对象...

    lvzishen 评论0 收藏0
  • 关于Python属性与实例属性的讨论

    摘要:之所以想写这个文章是因为碰巧看到网上一篇关于中类属性及实例属性区别的帖子。中属性的获取对于属性,我们通常采用类属性或实例属性的形式调用。最关键的地方在于两点理解是如何利用查找树的机制来模仿类及实例之间的关系理解动态语言是可以动态设置属性的 标题名字有点长。 之所以想写这个文章是因为碰巧看到网上一篇关于Pyhon中类属性及实例属性区别的帖子。因为我之前也被这个问题困扰过,今天碰巧看到了...

    neroneroffy 评论0 收藏0
  • 深入NUXT,看看一条命令行的背后到底发生什么

    摘要:一介绍随着社区的框架的发布,社区也终于诞生了属于自己的前后端同构框架。本文主要研究的运行原理,分析它从接收一条指令,到完成指令背后所发生的一系列事情。最后,通过来检查输出的是否存在问题,然后发出通知,表明可用。 showImg(https://segmentfault.com/img/bVIc9l?w=536&h=136); 一、介绍 Nuxt.js - Universal Vue.j...

    opengps 评论0 收藏0
  • Python学习之路21-序列构成的数组

    摘要:第行把具名元组以的形式返回。对序列使用和通常号两侧的序列由相同类型的数据所构成当然不同类型的也可以相加,返回一个新序列。从上面的结果可以看出,它虽抛出了异常,但仍完成了操作查看字节码并不难,而且它对我们了解代码背后的运行机制很有帮助。 《流畅的Python》笔记。接下来的三篇都是关于Python的数据结构,本篇主要是Python中的各序列类型 1. 内置序列类型概览 Python标准库...

    ralap 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<