Python中的旧样式类和新样式类之间有什么区别?
Python中的旧样式类和新样式类之间有什么区别?我应该在什么时候使用一个或另一个?来自: 直到Python2.1,旧式类是用户唯一可用的风格。 (旧式)类的概念与类型的概念无关: 如果Python中的旧样式类和新样式类之间有什么区别?,python,class,oop,types,new-style-class,Python,Class,Oop,Types,New Style Class,Python中的旧样式类和新样式类之间有什么区别?我应该在什么时候使用一个或另一个?来自: 直到Python2.1,旧式类是用户唯一可用的风格。 (旧式)类的概念与类型的概念无关: 如果x是一个旧式类的实例,那么x.\uuuuuu class\uuuuuu 指定x的类别,但类型(x)始终是 这反映了一个事实,即所有旧式实例都独立于 它们的类是用一个名为 例如 在Python2.2中引入了新样式的类,以统一类和类型的概念。 新样式的类只是用户定义的类型,不多也不少 如果x是一个新样式类的实例,那么
x
是一个旧式类的实例,那么x.\uuuuuu class\uuuuuu
指定x
的类别,但类型(x)
始终是
这反映了一个事实,即所有旧式实例都独立于
它们的类是用一个名为
例如
在Python2.2中引入了新样式的类,以统一类和类型的概念。
新样式的类只是用户定义的类型,不多也不少
如果x是一个新样式类的实例,那么type(x)
通常是
与x.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu类
相同(尽管这不保证–a
允许新样式的类实例重写返回的值
对于x.\uuuuu类\uuuuuu
)
引入新型类的主要动机是提供具有完整元模型的统一对象模型
它还有许多直接的好处,比如
子类大多数内置类型,或引入“描述符”,
这将启用计算属性
出于兼容性原因,类在默认情况下仍然是旧式的
通过指定另一个新样式类来创建新样式类
(即类型)作为父类,或“顶级类型”对象(如果没有)
需要另一位家长
新式阶级的行为不同于老式阶级
类中的一些重要细节除了什么类型
返回
其中一些更改是新对象模型的基础,如
调用特殊方法的方式。其他则是无法解决的“修复”
为了兼容性考虑,如方法
多重继承情况下的解析顺序
Python 3只有新样式的类
无论您是否从对象
创建子类,类都是新样式的
在Python3中
新样式类继承自
对象
,并且必须在Python2.2以后的版本中以同样的方式编写(即类类名(对象):
而不是类类名:
)。核心的变化是统一类型和类,其良好的副作用是它允许您从内置类型继承
阅读了解更多详细信息。声明方面:
新样式类继承自对象或其他新样式类
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
旧式的课程不会
class OldStyleClass():
pass
Python 3注意:
Python3不支持旧样式的类,因此上面提到的任何一种形式都会产生一个新样式的类。旧样式的类在属性查找方面仍然稍微快一些。这通常并不重要,但在性能敏感的Python 2.x代码中可能很有用:
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
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
在[3]中:A类:
…:def_uuuinit_uuu(self):
…:self.a=‘你好’
...:
在[4]中:B类(对象):
…:def_uuuinit_uuu(self):
…:self.a=‘你好’
...:
在[6]中:aobj=A()
[7]中:bobj=B()
在[8]:%timeit aobj.a中
10000000个循环,最佳3个:每个循环78.7纳秒
在[10]中:%timeit bobj.a
10000000个循环,最佳3个:每个循环86.9纳秒
Guido写了一篇关于Python中新样式和旧样式类的非常棒的文章
Python3只有一个新样式的类。即使您编写了一个“旧式类”,它也是隐式地从对象派生的
新样式类有一些旧样式类所没有的高级特性,例如super
,新的,一些神奇的方法,等等。新样式类可以使用super(Foo,self)
,其中Foo
是一个类,self
是一个实例
super(类型[,对象或类型])
返回一个代理对象,该对象将方法调用委托给类型为的父类或同级类。这对于访问类中已重写的继承方法非常有用。搜索顺序与getattr()使用的相同,只是跳过了类型本身
在Python3.x中,您只需在类中使用super()
,而无需任何参数。这里有一个非常实用的真/假区别。以下代码的两个版本之间的唯一区别是,在第二个版本中,Person继承自object。除此之外,这两个版本是相同的,但结果不同:
旧式班级
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>
>>>
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>
>>>
class Person():
_名称\u缓存={}
定义初始化(self,name):
self.name=名称
定义新名称(cls,名称):
返回cls.\u names\u cache.setdefault(名称,对象.\uuuu新的\uuuuu(cls,名称))
ahmed1=人(“Ahmed”)
ahmed2=人(“Ahmed”)
打印ahmed1是ahmed2
打印ahmed1
打印ahmed2
>>>假的
>>>
新型课堂
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>
>>>
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>
>>>
类人(对象):
_名称\u缓存={}
定义初始化(self,name):
self.name=名称
定义新名称(cls,名称):
返回cls.\u names\u cache.setdefault(名称,对象.\uuuu新的\uuuuu(cls,名称))
ahmed1=人(“Ahmed”)
ahmed2=人(“Ahmed”)
打印ahmed2是ahmed1
打印ahmed1
打印ahmed2
>>>真的
>>>
新旧风格课程之间的重要行为变化
- 增加
- MRO变更(解释如下)
- 增加
- 除非派生自
异常
(以下示例),否则无法引发新样式类对象
- 增加
MRO(方法解决顺序)已更改
其他答案中也提到了这一点,但这里有一个关于经典MRO和C3 MRO(用于新样式类)之间差异的具体示例