之间的区别是什么旧式和新式类蟒蛇?
-
09-06-2019 - |
题
之间的区别是什么旧式和新式类蟒蛇?当我应该用一个或另一个?
解决方案
从 http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes :
到蟒蛇2.1,旧样式的课程是仅有的味道可供用户使用。
这一概念的(旧式)类相关的概念的类型:如果
x
是的一个实例,一个旧式风格的类,然后x.__class__
指定的类的x
, 但type(x)
总是<type 'instance'>
.这反映出一个事实,即所有的旧风格的情况下,独立的 他们的班,实施一个内置的类型,称为 实例。
新式课程中引入Python2.2统一概念和类型.一种新式类是一个简单的用户定义的类型,没有更多,没有少.
如果x是一个实例,一种新式类,然后
type(x)
通常是 同x.__class__
(尽管这不是保证一个 新式类实例是允许的复盖值返回 对于x.__class__
).主要动机引入新式类是提供一个统一的对象模型和一个完整的元模型.
它也有一些直接的好处,如能力 子类的大多数建造类型,或引入的"描述", 其启用计算的特性。
由于兼容性原因、类仍旧式通过默认.
新式类的创建是通过指定的另一种新式类 (即一种类型)作为父母一类或"顶级"如果没有对象 其他的父母是必要的。
该行为的新式类不同于旧风格的 类在一些重要的细节,除了什么类型的 返回。
这些变化是根本性的新的对象模型,就像 这种特殊方法是援引。其他人是"修正"就不可能 以前实施的兼容性问题,就像的方法 决议顺序的情况下多个继承。
蟒蛇3只有具有新式类.
不管如果你的子类从
object
或者不是,类新的风格 在Python3.
其他提示
宣言--明智的:
新式类继承的对象,或者从另一个新式类。
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
旧式的类别。
class OldStyleClass():
pass
重要的行为改变之间旧的和新的类风格
MRO(方法解决顺序)改变
这是中提到的其他答案,但这里的一个具体的例子之间的差别经典的维修和C3MRO(中使用新式类)。
问题是以其属性(其中包括方法和成员的变量)的搜索多个继承。
经典的类 做一个深入的第一个搜索从左到右。停止上第一场比赛。他们没有 __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
周围Python2.5许多类可能提出的,围绕Python2.6此被删除。在Python2.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
旧风格的课程仍然是稍微快属性查询。这通常不是很重要的,但可能是有用的,在性能敏感蟒蛇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
Guido写了 里面的故事,在新式类, 一个真正伟大的文章有关的新式和旧风格的类蟒蛇。
蟒蛇3只有新式类,甚至如果你写一个'旧风格的类的,它是隐含来自 object
.
新式类具有某些先进的功能缺乏在旧风格的类别,例如 super
和新的 C3mro, 一些神奇的方法,等等。
这是一个非常实际的、真正的/误差。唯一的区别在两个版本之间以下代码是在第二版个人继承的对象。另外,这两个版本完全相同,但具有不同的结果:
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
<__main__.Person instance at 0xb74acf8c>
<__main__.Person instance at 0xb74ac6cc>
>>>
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
<__main__.Person object at 0xb74ac66c>
<__main__.Person object at 0xb74ac66c>
>>>
新式类继承 object
并必须作为这样的Python2.2起的(即 class Classname(object):
而不是的 class Classname:
).核心的变化是统一的种类和类别,并且漂亮的副作用是,它可以让你继承自内在的类型。
阅读 descrintro 更多的细节。
新的风格可能使用课程 super(Foo, self)
哪里 Foo
是一类的, self
是的实例。
super(type[, object-or-type])
返回一个代理的对象代表的方法的呼吁父母或兄弟姐妹类的类型。这是有用的访问继承的方法已经复盖的一类。搜索顺序是一样的,用于通过getattr()除的类型本身就是跳过。
在Python3.x你可以简单地使用 super()
内部一级没有参数。
或者说,应始终使用新式的课程, 除非 你们的代码需要的工作版本的蟒蛇超过2.2.