Python中的旧样式类和新样式类有什么区别?什么时候我应该用一种或另一种?
当前回答
Guido写了关于新型类的内幕,这是一篇关于Python中的新型和老式类的很棒的文章。
Python 3只有new-style类。即使你写了一个“老式类”,它也是隐式地从object派生的。
新型类具有一些老式类所缺乏的高级特性,如super,新的C3 mro,一些神奇的方法等。
其他回答
新的样式类可以使用super(Foo, self),其中Foo是类,self是实例。
超级(类型、对象或者类型) 返回一个代理对象,该对象将方法调用委托给类型的父类或兄弟类。这对于访问在类中被重写的继承方法非常有用。除了类型本身被跳过之外,搜索顺序与getattr()所使用的相同。
在Python 3中。X你可以简单地在类中使用super()而不带任何参数。
Guido写了关于新型类的内幕,这是一篇关于Python中的新型和老式类的很棒的文章。
Python 3只有new-style类。即使你写了一个“老式类”,它也是隐式地从object派生的。
新型类具有一些老式类所缺乏的高级特性,如super,新的C3 mro,一些神奇的方法等。
新旧样式类之间的重要行为变化
超级补充道 MRO变更(解释如下) 描述符添加 除非派生自Exception,否则不能引发new样式类对象(如下例) __slots__补充道
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
这里有一个非常实际的真/假的区别。以下代码的两个版本之间的唯一区别是,在第二个版本中,Person从object继承。除此之外,这两个版本是相同的,但结果不同:
Old-style classes 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 <__main__.Person instance at 0xb74acf8c> <__main__.Person instance at 0xb74ac6cc> >>> New-style classes 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 <__main__.Person object at 0xb74ac66c> <__main__.Person object at 0xb74ac66c> >>>
对于属性查找,旧样式的类仍然稍微快一些。这通常并不重要,但在性能敏感的Python 2中可能很有用。x代码:
In [3]: class A: ...: def __init__(self): ...: self.a = 'hi there' ...: In [4]: class B(object): ...: def __init__(self): ...: self.a = 'hi there' ...: In [6]: aobj = A() In [7]: bobj = B() In [8]: %timeit aobj.a 10000000 loops, best of 3: 78.7 ns per loop In [10]: %timeit bobj.a 10000000 loops, best of 3: 86.9 ns per loop
推荐文章
- 如何为python模块的argparse部分编写测试?
- 在python中是否有用于均方根误差(RMSE)的库函数?
- 如何从matplotlib (pyplot。Figure vs matplotlib。figure) (frameon=False matplotlib中有问题)
- django test app error -在创建测试数据库时出现错误:创建数据库的权限被拒绝
- 克隆对象没有引用javascript
- 识别使用pip安装的python包的依赖关系
- 从字符串变量导入模块
- 如何删除Python中的前导空白?
- python中的assertEquals和assertEqual
- 如何保持Python打印不添加换行符或空格?
- PHP中接口的意义是什么?
- 为什么Python的无穷散列中有π的数字?
- Python 3.7数据类中的类继承
- 如何在PyTorch中初始化权重?
- 计数唯一的值在一列熊猫数据框架像在Qlik?