Python实例一个类背后发生了什么
作者:outshineamaze 发布时间:2023-05-19 05:44:18
首先来看一个例子,正常情况下我们定义并且实例一个类如下
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中有两个最基本的对象,<type ‘object'> 和 <type ‘type'>,这两个对象是所有对象的起源。
1、<type ‘type'>的类型是<type ‘type'>(它本身),<type ‘type'>的父类是<type ‘object'>
2、<type ‘object'>的类型是<type ‘type'>,<type ‘object'>没有父类
在Python对象系统中,<type ‘object'>和<type ‘type'>的关系就像鸡和蛋的关系,不能说谁先于(创建)谁,两者是相互依赖的,共同构成了Python对象系统的基础.有点难理解,不过没有关系,知道有种这么两个东西就好了,比较我们也不是设计Python的人,没有必要搞的那么清楚.
二、类的创建
主要有两种方式,不过本质上都是一样的,都是通过type类来实例一个用户类
//普通方式
class Foo(object):
def func(self):
print 'hello wupeiqi'
//特殊方式(type类的构造函数)
def func(self):
print 'hello wupeiqi'
Foo = type('Foo',(object,), {'func': func})
#type第一个参数:类名
#type第三个参数:类的成员
由上面可以看出来 , Foo类是由type类实例而来,那么具体的创建的过程是怎么样的呢,接着往下面看:
来了解几个概念
new 和 __init()和__metaclass__:
__new__函数是实例一个类所要调用的函数,每当我们调用obj = Foo()来实例一个类时,都是先调用__new__()
然后再调用__init__()函数初始化实例. __init__()在__new__()执行后执行,
类中还有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
三、阐述运行过程
1、mytype产生一个叫做Foo的实例,主要的原理就是设置了,__metaclass__=MyTypoe,这样就指定mytype类来实例foo类,如果Python没有找到__metaclass__,它会继续在(父类)中寻找 __metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
2、mytype类中的__new__方法返回了一个对象,所有的Python实例都是这句代码创建的type.__new__(cls,name,bases,attrs)
3、mytype的__init__()函数初始化Foo类,在这里我们可以和在__new__()函数一样设置Foo类的attr属性,比如类中的方法,字段属性等
4、和Foo类的创建过程一样,studen类继承了Foo类,所以重复123步骤,得到一个studen类
5、当用户使用Foo()或者studen()来实例类时,会默认调用类中的_new_()方法,要是之类里面没有这个方法就到父类里面寻找__new__(),我们可以充分利用这个new函数,比如来实现Python中的单例模式,或者对类成员进行批量的修改等等.
6、产生了一个实例后马上执行__init__()函数,进行初始化实例,
7、由上面的运行结果可以看出,其中Foo和studen类的类型是<class '__main__.MyType'>,这也证明了Foo类和studen类都是由MyType实例而来…而第三个例子,可以看出Foo2类的类型是<type 'type'>,这个并不例外,Foo2继承了object类,(这个,还是跳过吧,前面已经讲过type和object相爱相杀的关系了)
总结
首先,你知道了类其实是能够创建出类实例的对象。好吧,事实上,类本身也是实例,当然,它们是元类的实例。Python中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了type。type实际上是它自己的元类,在纯Python环境中这可不是你能够做到的,这是通过在实现层面耍一些小手段做到的。其次,元类是很复杂的。对于非常简单的类,你可能不希望通过使用元类来对类做修改。你可以通过其他两种技术来修改类:
1、Monkey patching
2、class decora


猜你喜欢
- Python中编码问题:u'\xe6\x97\xa0\xe5\x90\x8d' 类型的转为utf-8的解决办法相信小伙伴们遇
- Protocol Buffers (类似XML的一种数据描述语言)最新版本2.3里,protoc—py_out命令只生成原生的P
- 目前很多网站都使用ajax技术动态加载数据,和常规的网站不一样,数据时动态加载的,如果我们使用常规的方法爬取网页,得到的只是一堆html代码
- 前言嗨,彦祖们,不会过圣诞了还是一个人吧?今天我们来讲一下如何用python来画一个圣诞树,学会就快给那个她发过去吧,我的朋友圈已经让圣诞树
- 关于python读取xml文章很多,但大多文章都是贴一个xml文件,然后再贴个处理文件的代码。这样并不利于初学者的学习,希望这篇文章可以更通
- 一、argparse介绍官方文档argparse 模块是 Python 内置的一个用于命令项选项与参数解析的模块,argparse 模块可以
- 先写一个SQLSELECT DISTINCT from_idFROM codWHERE cod.from_id NOT IN (37, 56
- 如下所示: static void Main()&nbs
- 将el-switch值true、false改为number类型的1和0需求描述后端传回的status值为1(number类型)对应el-sw
- 对于access数据库的日期时间类型字段存储的日期,直接从数据库中读出显示的效果是带时间的如,2009-06-13 18:00 ,如果只是希
- 根据Nicholas的说法,有四种代码会拖慢脚本的运行,并最终导致脚本失控。分别是次数过多的同步循环、庞大的函数体、不恰当的递归和不合理的D
- 目录简介开发工具实现代码爬取效果Github地址:简介使用Python Tkinter开发一个爬取B站直播弹幕的工具,启动后在弹窗中输入房间
- 本文实例讲述了Python实现繁體转为简体的方法。分享给大家供大家参考,具体如下:这里需要用到两个文件,可以点击此处本站下载源文件:zh_w
- 这篇文章主要介绍了Python @property装饰器原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 一、项目工程目录:二、具体工程文件代码:1、新建一个包名:common(用于存放基本函数封装)(1)在common包下新建一个base.py
- 字符串字符串常用操作拼接字符串拼接字符串需要使用‘+’运算符可完成对多个字符串的拼接。如str =
- 1 无参数情况配置URL及其视图如下:(r'^hello/$', hello)def hello(request): &nb
- 批量修改: EXEC sp_MSforeachtable 'exec sp_changeob
- 如下所示:# coding:utf-8'''求两个字符串的最长公共子串思想:建立一个二维数组,保存连续位相同与否的状
- 这是我研究网页切片算法的一个汇总想法。之前我写过:一种面向搜索引擎的网页分块、切片的原理,实现和演示,随着工作的深入,逐渐碰到以