当前位置:首页 » 编程语言 » python新式类和经典类

python新式类和经典类

发布时间: 2022-04-16 14:06:41

python2.7.3和3.3.2的区别

转自:http://my.oschina.net/chihz/blog/123437
这边只说明面向对象方面的,其他方面见上面链接

面向对象
(1) 经典类和新式类
Python OO最神奇的地方就是有两种类,经典类和新式类。
新式类跟经典类的差别主要是以下几点:
1. 新式类对象可以直接通过__class__属性获取自身类型:type
2. 继承搜索的顺序发生了改变,经典类多继承属性搜索顺序: 先深入继承树左侧,再返回,开始找右侧;新式类多继承属性搜索顺序: 先水平搜索,然后再向上移动
3. 新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中。
4. 新式类增加了__getattribute__方法
Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,不必显式的继承object
python 2.x:
>>> ClassicClass.__class__
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
AttributeError: class ClassicClass has no attribute '__class__'
>>> class NewClass(object):
... pass
...
>>> NewClass.__class__

python 3.x:
>>> class NewClass:pass
...
>>> NewClass.__class__
<class 'type'>
(2) 无绑定方法
在Python 2.x中除了类方法和静态方法,其余的方法都必须在第一个参数传递self跟实例绑定,但是在Python 3.x中废除了这条规定,允许方法不绑定实例,这样的方法跟普通的函数没有区别:
Python 2.x:
>>> class MyClass:
... def function():
... print "function"
...
>>> MyClass.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method function() must be called with MyClass instance as first argument (got nothing instead)
>>> m = MyClass()
>>> m.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: function() takes no arguments (1 given)
Python 3.x:
>>> class MyClass:
... def function():
... print("function")
...
>>> MyClass.function()
function
>>> m = MyClass()
>>> m.function()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: function() takes no arguments (1 given)
(3) 重要的重载
1. next()和__next__():这应该是继print之后第二大坑爹的不兼容吧,Python程序漫山遍野都是迭代器,但是2和3之间迭代器的实现接口方法名是不同的……嗯,啥都不说了。
2. 分片拦截:Python 3.x之前, 类可以定义__getslice__和__setslice__方法来专门拦截分片,并且这两个方法优先于__getitem__和__setitem__, 但是Python 3.x时代这俩方法再也不存在了,全部的工作都交给了__getitem__和__setitem__,因此在使用这两个方法之前要先判断传递进参数的类型是不是slice对象。
3. __bool__方法:我们知道Python中默认将所有的空对象定义为布尔意义上的False,在自己定义的类中我们也可以加入自定义的布尔判断标准,在2.x中这个方法名叫做__nonzero__, 这个名字显然非常不直观并且不科学!所有考试交白卷的孩子我们都要否定他们的才能么?显然不能!因此Python 3.x中这个方法被重名命为__bool__
4. 3.x 取消了用于大小比较的__cmp__方法,取而代之的是:__lt__、__gt__、__le__、__ge__、__eq__、__ne__,嗯,我感觉这个想法真是不能苟同……有谁能说服我给我洗脑让我爱上这一堆__lt__、__gt__、__le__、__ge__、__eq__、__ne__么。。。
(4) 类修饰器
在我的上一篇博客中秀了一把函数装饰器在表单验证中的使用,http://my.oschina.net/chihz/blog/122897
在3.x的时代,类也有装饰器了,这个装饰器威力巨大,能把装饰的类搞的面目全非,总之想怎么搞就怎么搞,用法同函数装饰器基本一致,只不过传递的参数是类型:
>>> def shutdown(cls):
... def shutdown_func(self):
... print("do something...")
... cls.shutdown = shutdown_func
... return cls
...
>>> @shutdown
... class Test:pass
...
>>> t = Test()
>>> t.shutdown()
do something...

异常

先来看一段代码
python 2.x:
>>> class Person:
... def __init__(self, msg):
... self.msg = msg
...
>>> try:
... raise Person, "woca"
... except Person as p:
... print p.msg
...
woca
python 3.x:
>>> class Person:
... def __init__(self, msg):
... self.msg = msg
...
>>> try:
... raise Person("woca")
... except Person as p:
... print(p.msg)
Traceback (most recent call last):
File "<stdin>", line 2, in <mole>
TypeError: exceptions must derive from BaseException

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<stdin>", line 3, in <mole>
TypeError: catching classes that do not inherit from BaseException is not allowed
>>>
接下来说不同:
1. 在2.x时代,所有类型的对象都是可以被直接抛出的,在3.x时代,只有继承自BaseException的对象才可以被抛出。
2. 2.x raise语句使用逗号将抛出对象类型和参数分开,3.x取消了这种奇葩的写法,直接调用构造函数抛出对象即可。
在2.x时代,异常在代码中除了表示程序错误,还经常做一些普通控制结构应该做的事情,在3.x中可以看出,设计者让异常变的更加专一,只有在错误发生的情况才能去用异常捕获语句来处理。

② Python新式类和经典类的区别

A.在Python里凡是继承了object的类,都是新式类
B.Python3里只有新式类
C.Python2里面继承object的是新式类,没有写父类的是经典类
D.经典类目前在Python里基本没有应用
E.保持class与type的统一对新式类的实例执行a.class与type(a)的结果是一致的,对于旧式类来说就不一样了
F.对于多重继承的属性搜索顺序不一样新式类是采用广度优先搜索,旧式类采用深度优先搜索

③ python经典类和新式类为啥效率差这么多

你的测试时间差别太夸张了,肯定受到其他程序的影响,用timeit测量了一下更好。

如果all_except函数是 current != node这种,大概旧式类的对象创建和遍历加的操作是新式类对象的时间2倍。但是如果把all_except改成 while not current is node:那么旧式类对象的操作时间就比新式类少(新式类有一个descriptor的查找过程),如果给新式类增加__slots__,时间能稍微降一点,但还是比旧式类多。

所以问题应该是 != 操作没有 not is 操作高效,is操作使用了id,应该类似比较内存地址那种。而!=可能做了更多的事情。

下面是代码。

import time
class dblink:
def __init__(self,index=0):
self.index = index
self.prev = self
self.next = self

def insert(self,index):
node = dblink(index)
node.prev = self.prev
node.next = self
self.prev.next = node
self.prev = node

class nt_dblink(object):
__slots__=('index','prev','next')
def __init__(self,index=0):
self.index = index
self.prev = self
self.next = self

def insert(self,index):
node = nt_dblink(index)
node.prev = self.prev
node.next = self
self.prev.next = node
self.prev = node

def all_except(node):
current = node.next
while not current is node:
yield current
current = current.next

def test1():
head = dblink()
for i in range(100000):
head.insert(i)

for node in all_except(head):
node.index+=1

def test2():
head = nt_dblink()
for i in range(100000):
head.insert(i)

for node in all_except(head):
node.index+=1

if __name__=='__main__':
import timeit
print(timeit.timeit("test1()", setup="from __main__ import test1",number=1))
print(timeit.timeit("test2()", setup="from __main__ import test2",number=1))

④ python经典类和新式类的区别

在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类,则称之为“经典类”。
“新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。

⑤ Python新式类和旧式类的区别

1)首先,写法不一样:

classA:#旧式类
pass

classB(object):#新式类
pass


2)在多继承中,新式类采用广度优先搜索,而旧式类是采用深度优先搜索。
3)新式类更符合OOP编程思想,统一了python中的类型机制。

⑥ Python 为什么要继承 object 类

继承 object 类的是新式类,不继承 object 类的是经典类
2.2以前的时候type和object还不统一. 在2.2统一以后到3之间, 要用class Foo(object)来申明新式类, 因为他的type是 < type 'type' > .不然的话, 生成的类的type就是 < type 'classobj' >
Python2 里的新式类, 其特点如下:

low-level constructors named __new__() – 低级别的构造函数.
Note: Python 的 class __init__ 并不是其他语言意义上的构造函数,
在 new 创建实例后对实例属性初始化的函数.
descriptors, a generalized way to customize attribute access – 描述符.
或者说描述符协议支持.descriptor protocol __get__, __set__ ,__delete__ 等,
可以阅读 descriptor 文档
static methods and class methods - 静态方法和类方法
properties (computed attributes) – 属性访问 setter getter.
decorators (introced in Python 2.4) – 装饰器.
现在装饰器语法糖遍布各Python框架.
slots – 用户设置后可以限定实例的属性.
在 Python2 中替代 __dict__, 可以节省近 2/3 内存, Python3 中可以
不因为优化内存使用率而使用 slots, 因为 __dict__ 结构内存做了优化,
Note: __dict__ 并不是 Python 意义上的内置的 dict, 其实是一个 proxy 类.
a new Method Resolution Order (MRO) – MRO 方法解析次序改变
(由左递归改为C3算法)

⑦ python中怎么组织这样的类

我的思路是做类的继承,不管是新式类还是经典类,在Python3上都是“广度优先”,使用继承的方式,当某个类的实例条件成立就转向执行本身。

⑧ Python中的旧样式类和新样式类有什么区别

  1. 在Python 2.1之前,旧式类是用户可用的唯一样式。

  2. (旧式)类的概念与类型的概念无关:如果x是旧式类的实例,则x.__class__指定的类x,但type(x)始终为<type
    'instance'>。这反映了这样一个事实,即所有旧式实例(独立于其类)均使用称为实例的单个内置类型实现。

  3. 在Python 2.2中引入了新的类,以统一class和type的概念。新型类只是用户定义的类型,不多也不少。如果x是新样式类的实例,则type(x)通常与x 相同x.__class__(尽管不能保证–允许新样式类实例覆盖为返回的值x.__class__)。

  4. 引入新型类的主要动机是提供具有完整元模型的统一对象模型。

  5. 它还具有许多直接的好处,例如能够对大多数内置类型进行子类化,或者引入了“描述符”,以启用计算属性。出于兼容性原因,默认情况下,类仍为旧样式。通过将另一个新样式类(即一种类型)指定为父类或“顶级类型”对象(如果不需要其他父类)来创建新样式类。

  6. 新样式类的行为与旧样式类的行为不同,除了返回什么类型外,还有许多重要的细节。其中一些更改是新对象模型的基础,例如调用特殊方法的方式。其他是出于兼容性考虑而无法实现的“修复程序”,例如在多重继承的情况下的方法解析顺序。

  7. Python 3仅具有新型类。无论是否从中继承子类object,类都是Python 3中的新型样式。

⑨ python的多重继承问题

楼上的回答的很正确,简单来说:在对类D进行实例化的时候,你依次对类C和类A进行了初始化,结果就会以后初始化的B为准了

实际上在子类里并不需要去初始化父类,你在实例化子类的同时,继承自父类的对象都会被创建

classA(object):
def__init__(self):
self.a=1

classB(A):
def__init__(self):
self.a=2
self.b=2
classC(B,A):
pass

>>> c = C()

>>> c.a

>>> 2

另外补充一下。父类为新式类的情况下,继承顺序是有影响的。继承顺序上,经典类是深度优先,新式类是广度优先,两种混用的话,分分钟就晕乎了。可以去多做做实验,好好了解。

热点内容
设计一个虚拟存储区 发布:2024-05-03 05:24:18 浏览:926
压缩机如何配置电容 发布:2024-05-03 05:20:55 浏览:108
pythonconvert函数 发布:2024-05-03 05:19:54 浏览:526
androidspinner下拉 发布:2024-05-03 05:14:05 浏览:588
go源码编译2021 发布:2024-05-03 05:02:27 浏览:285
两驱车买哪个配置最好 发布:2024-05-03 04:41:42 浏览:803
如何给服务器上传文件 发布:2024-05-03 04:28:47 浏览:708
android仿微信底部菜单 发布:2024-05-03 04:09:34 浏览:695
LOL脚本识别 发布:2024-05-03 03:53:14 浏览:793
祁东福祥惠民卡初始密码多少 发布:2024-05-03 03:36:02 浏览:248