python 新式类和旧式类_Python中旧样式类与新样式类有什么区别?

Python的新样式类与旧样式类主要区别在于新样式类具备更丰富的特性和功能,如super、C3 MRO等。新样式类允许使用super()进行方法调用,改进了多重继承的行为。旧样式类在Python3中不再支持,所有类默认为新样式类。新样式类的__new__()方法在某些场景下会影响实例化行为,如示例所示。
摘要由CSDN通过智能技术生成

Python中旧样式类与新样式类有什么区别? 什么时候应该使用其中一个?

#1楼

声明方式:

新样式类从object或另一个新样式类继承。

class NewStyleClass(object):

pass

class AnotherNewStyleClass(NewStyleClass):

pass

老式的类没有。

class OldStyleClass():

pass

Python 3注意:

Python 3不支持旧样式类,因此上述任何一种形式都会生成新样式类。

#2楼

Guido撰写了有关New-Style Classes的The Inside Story ,这是一篇关于Python中的新风格和旧风格类的非常不错的文章。

Python 3只有新样式的类,即使您编写“旧样式的类”,它也是隐式派生自object 。

新式类具有一些旧式类所缺少的高级功能,例如super和新的C3 mro以及一些神奇的方法等。

#3楼

新样式类可以使用super(Foo, self) ,其中Foo是类,而self是实例。

super(type[, object-or-type])

返回将方法调用委托给类型的父级或同级类的代理对象。 这对于访问已在类中重写的继承方法很有用。 搜索顺序与getattr()使用的顺序相同,只是类型本身被跳过。

在Python 3.x中,您可以在没有参数的类中简单地使用super() 。

#4楼

这是一个非常实际的,正确/错误的区别。 以下代码的两个版本之间的唯一区别是,在第二个版本中,Person继承自object。 除此之外,两个版本相同,但结果不同:

1)老式类

class Person():

_names_cache = {}

def __init__(self,name):

self.name = name

def __new__(cls,name):

return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")

ahmed2 = Person("Ahmed")

print ahmed1 is ahmed2

print ahmed1

print ahmed2

>>> False

>>>

2)新型类

class Person(object):

_names_cache = {}

def __init__(self,name):

self.name = name

def __new__(cls,name):

return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")

ahmed2 = Person("Ahmed")

print ahmed2 is ahmed1

print ahmed1

print ahmed2

>>> True

>>>

#5楼

新旧样式类之间的重要行为更改

超级添加

MRO已更改(说明如下)

添加了描述符

除非从Exception派生,否则无法引发新样式类对象(下面的示例)

MRO(方法解析顺序)已更改

它在其他答案中也提到过,但是这里有一个具体示例,说明了经典MRO和C3 MRO(用于新样式类)之间的区别。

问题是在多重继承中搜索属性(包括方法和成员变量)的顺序。

经典类从左到右进行深度优先搜索。 停在第一场比赛。 它们没有__mro__属性。

class C: i = 0

class C1(C): pass

class C2(C): i = 2

class C12(C1, C2): pass

class C21(C2, C1): pass

assert C12().i == 0

assert C21().i == 2

try:

C12.__mro__

except AttributeError:

pass

else:

assert False

新式类 MRO在单个英语句子中合成起来更加复杂。 在这里详细解释。 它的特性之一是,只有在所有基类的派生类都被查找之后才搜索基类。 它们具有显示搜索顺序的__mro__属性。

class C(object): i = 0

class C1(C): pass

class C2(C): i = 2

class C12(C1, C2): pass

class C21(C2, C1): pass

assert C12().i == 2

assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)

assert C21.__mro__ == (C21, C2, C1, C, object)

除非从Exception派生,否则无法引发新样式类对象

在Python 2.5左右,可能会引发许多类,而在Python 2.6左右,这已被删除。 在Python 2.7.3上:

# OK, old:

class Old: pass

try:

raise Old()

except Old:

pass

else:

assert False

# TypeError, new not derived from `Exception`.

class New(object): pass

try:

raise New()

except TypeError:

pass

else:

assert False

# OK, derived from `Exception`.

class New(Exception): pass

try:

raise New()

except New:

pass

else:

assert False

# `'str'` is a new style object, so you can't raise it:

try:

raise 'str'

except TypeError:

pass

else:

assert False

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值