python继承object
1. python对象
众所周知,Python是一门面向对象的语言,在Python无论是数值、字符串、函数亦或是类型、类,都是对象。
对象是在 堆 上分配的结构,我们定义的所有变量、函数等,都存储于堆内存,而变量名、函数名则是一个存储于 栈 中、指向堆中具体结构的引用。
要想深入学习Python,首先需要知道Python对象的定义。
我们通常说的Python都是指CPython,底层由C语言实现,源码地址: cpython [GitHub]
Python对象的定义位于 Include/object.h ,是一个名为 PyObject 的结构体:
Python中的所有对象都继承自PyObejct,PyObject包含一个用于垃圾回收的双向链表,一个引用计数变量 ob_refcnt 和 一个类型对象指针 ob_type
从PyObejct的注释中,我们可以看到这样一句:每个指向 可变大小Python对象 的指针也可以转换为 PyVarObject* (可变大小的Python对象会在下文中解释)。 PyVarObejct 就是在PyObject的基础上多了一个 ob_size 字段,用于存储元素个数:
在PyObject结构中,还有一个类型对象指针 ob_type ,用于表示Python对象是什么类型,定义Python对象类型的是一个 PyTypeObject 接口体
实际定义是位于 Include/cpython/object.h 的 _typeobject :
在这个类型对象中,不仅包含了对象的类型,还包含了如分配内存大小、对象标准操作等信息,主要分为:
以Python中的 int类型 为例,int类型对象的定义如下:
从PyObject的定义中我们知道,每个对象的 ob_type 都要指向一个具体的类型对象,比如一个数值型对象 100 ,它的ob_type会指向 int类型对象PyLong_Type 。
PyTypeObject结构体第一行是一个PyObject_VAR_HEAD宏,查看宏定义可知PyTypeObject是一个变长对象
也就是说,归根结底 类型对象也是一个对象 ,也有ob_type属性,那 PyLong_Type 的 ob_type 是什么呢?
回到PyLong_Type的定义,第一行 PyVarObject_HEAD_INIT(&PyType_Type, 0) ,查看对应的宏定义
由以上关系可以知道, PyVarObject_HEAD_INIT(&PyType_Type, 0) = { { _PyObject_EXTRA_INIT 1, &PyType_Type } 0} ,将其代入 PyObject_VAR_HEAD ,得到一个变长对象:
这样看就很明确了,PyLong_Type的类型就是PyType_Typ,同理可知, Python类型对象的类型就是PyType_Type ,而 PyType_Type对象的类型是它本身
从上述内容中,我们知道了对象和对象类型的定义,那么根据定义,对象可以有以下两种分类
Python对象定义有 PyObject 和 PyVarObject ,因此,根据对象大小是否可变的区别,Python对象可以划分为 可变对象(变长对象) 和 不可变对象(定长对象)
原本的对象a大小并没有改变,只是s引用的对象改变了。这里的对象a、对象b就是定长对象
可以看到,变量l仍然指向对象a,只是对象a的内容发生了改变,数据量变大了。这里的对象a就是变长对象
由于存在以上特性,所以使用这两种对象还会带来一种区别:
声明 s2 = s ,修改s的值: s = 'new string' ,s2的值不会一起改变,因为只是s指向了一个新的对象,s2指向的旧对象的值并没有发生改变
声明 l2 = l ,修改l的值: l.append(6) ,此时l2的值会一起改变,因为l和l2指向的是同一个对象,而该对象的内容被l修改了
此外,对于 字符串 对象,Python还有一套内存复用机制,如果两个字符串变量值相同,那它们将共用同一个对象:
对于 数值型 对象,Python会默认创建0~2 8 以内的整数对象,也就是 0 ~ 256 之间的数值对象是共用的:
按照Python数据类型,对象可分为以下几类:
Python创建对象有两种方式,泛型API和和类型相关的API
这类API通常以 PyObject_xxx 的形式命名,可以应用在任意Python对象上,如:
使用 PyObjecg_New 创建一个数值型对象:
这类API通常只能作用于一种类型的对象上,如:
使用 PyLong_FromLong 创建一个数值型对象:
在我们使用Python声明变量的时候,并不需要为变量指派类型,在给变量赋值的时候,可以赋值任意类型数据,如:
从Python对象的定义我们已经可以知晓造成这个特点的原因了,Python创建对象时,会分配内存进行初始化,然后Python内部通过 PyObject* 变量来维护这个对象,所以在Python内部各函数直接传递的都是一种泛型指针 PyObject* ,这个指针所指向的对象类型是不固定的,只能通过所指对象的 ob_type 属性动态进行判断,而Python正是通过 ob_type 实现了多态机制
Python在管理维护对象时,通过引用计数来判断内存中的对象是否需要被销毁,Python中所有事物都是对象,所有对象都有引用计数 ob_refcnt 。
当一个对象的引用计数减少到0之后,Python将会释放该对象所占用的内存和系统资源。
但这并不意味着最终一定会释放内存空间,因为频繁申请释放内存会大大降低Python的执行效率,因此Python中采用了内存对象池的技术,是的对象释放的空间会还给内存池,而不是直接释放,后续需要申请空间时,优先从内存对象池中获取。
2. python的class中的object是什么意思
object 是指这个类继承的最顶级的对象。python3.x 中已经可以省略object,可直接
classSample():
pass
3. python中的instance是什么对象类型
面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
仍以Student类为例,在Python中,定义类是通过class关键字:
class Student(object):
pass
class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>
可以看到,变量bart指向的就是一个Student的实例,后面的0x10a67a590是内存地址,每个object的地址都不一样,而Student本身则是一个类。
可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:
>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59
和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
4. python 添加了这个奇怪的叫做 object 的 class,它究竟有什么含义
在Python里,有一句话叫,一切皆对象。而对象的英文单词就是object。
换句话这个object就代表了Python中的一切,开发Python的龟叔已经给object类定义常用的属性和方法供认识使用。
当在Python2中,你定义类的时候,加上object,用内置函数dir(你定义类的名字)查看属性和方法,你定义的类会默认继承object这个基类(父类)的属性和方法。如果不给object参数,dir时就只有你自己定义属性和方法,没有继承object的。
你可以下去动手试试(我是手机端回答的问题,抱歉无法演示截图)
然后,如果你使用的是Python3,当你定义类的时候,给了object参数就继承。不给object参数也会默认继承。不管你是
class A:
还是 class A():
都会自动的被Python识别为:
class A(object)(这也是Python3更人性化的一点)
5. Python 为什么要继承 object 类
没有规定必须继承OBJECT类。OBJECT类只是面向对象语言继承精神的一种表现。例如OBJECTC,C++等语言在标准库中都将所有类的基类定义位OBJECT,这样的好处就是最大限度的利用代码重用的的精神。但是不通语言中的OBJECT类的作用又很不一样所以看看下面的介绍:回到PYTHON中为什么要集成OBJECT:low-levelconstructorsnamed__new__()–低级别的构造函数.Note:Python的class__init__并不是其他语言意义上的构造函数,在new创建实例后对实例属性初始化的函数.descriptors,–描述符.或者说描述符协议支持.descriptorprotocol__get__,__set__,__delete__等,可以阅读descriptor文档staticmethodsandclassmethods-静态方法和类方法properties(computedattributes)–属性访问settergetter.decorators(introcedinPython2.4)–装饰器.现在装饰器语法糖遍布各Python框架.slots–用户设置后可以限定实例的属性.在Python2中替代__dict__,可以节省近2/3内存,Python3中可以不因为优化内存使用率而使用slots,因为__dict__结构内存做了优化,Note:__dict__并不是Python意义上的内置的dict,其实是一个proxy类.anewMethodResolutionOrder(MRO)–MRO方法解析次序改变(由左递归改为C3算法)可能上面的你看着不太理解。通俗说一下py2.2后继承object的目的是使这个类成为newstyleclass,没有继承object的为传统classicclass,在本机进行了测试,环境为py2.7.3classFoo(object):passclassFoo1:passprinttype(Foo),type(Foo1)printdir(Foo)printdir(Foo1)printisinstance(Foo,object)printisinstance(Foo1,object)结果如下:['__class__','__delattr__','__dict__','__doc__','__format__','__getattribute__','__hash__','__init__','__mole__','__new__','__rece__','__rece_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__']['__doc__','__mole__']TrueTrue(这个True有些疑问,Foo1不应是object的实例啊)
6. python 添加了这个奇怪的叫做 object 的 class,它究竟有什么含义
在Python里,有一句话叫,一切皆对象。而对象的英文单词就是object。
换句话这个object就代表了Python中的一切,开发Python的龟叔已经给object类定义常用的属性和方法供认识使用。
当在Python2中,你定义类的时候,加上object,用内置函数dir(你定义类的名字)查看属性和方法,你定义的类会默认继承object这个基类(父类)的属性和方法。如果不给object参数,dir时就只有你自己定义属性和方法,没有继承object的。
你可以下去动手试试(我是手机端回答的问题,抱歉无法演示截图)
然后,如果你使用的是Python3,当你定义类的时候,给了object参数就继承。不给object参数也会默认继承。不管你是
class
A:
还是
class
A():
都会自动的被Python识别为:
class
A(object)(这也是Python3更人性化的一点)
7. python中的object类有何作用
object是一个基类,或称之为元类。
在python2.x上,不继承object类的称之为经典类,继承了object类的称之为新式类
关于它们的区别,你可以阅读以下python2手册中的这个部分:
https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
8. python中的instance是什么对象类型
在python2中,如果定义类时继承了object,那么实例化后对象的type就是该类
>>>
class
Apple(object):
pass
...
>>>
red_apple
=
Apple()
>>>
type(red_apple)
<class
'__main__.Apple'>
>>>
但如果定义类的时候没有继承object,实例化后对象的type将会是
instance
>>>
class
Apple():
pass
...
>>>
green_apple
=
Apple()
>>>
type(Apple)
<type
'instance'>
>>>
去看urllib2的源代码,你会发现build_opener返回的对象是从这个东西继承而来的:
class
BaseHandler:
def
add_parent(self,
parent):
self.parent
=
parent
def
close(self):
self.parent
=
None
它没有继承object,所以,它的type是instance
继承object的类的写法叫做
New-style
classes,是在
python
2.2
中引入的,之前的写法被称作
Old
clasess或
Classic
classes