Python中的旧样式类和新样式类有什么区别?什么时候我应该用一种或另一种?
当前回答
从新型和经典类:
Up to Python 2.1, old-style classes were the only flavour available to the user. The concept of (old-style) class is unrelated to the concept of type: if x is an instance of an old-style class, then x.__class__ designates the class of x, but type(x) is always <type 'instance'>. This reflects the fact that all old-style instances, independently of their class, are implemented with a single built-in type, called instance. New-style classes were introduced in Python 2.2 to unify the concepts of class and type. A new-style class is simply a user-defined type, no more, no less. If x is an instance of a new-style class, then type(x) is typically the same as x.__class__ (although this is not guaranteed – a new-style class instance is permitted to override the value returned for x.__class__). The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model. It also has a number of immediate benefits, like the ability to subclass most built-in types, or the introduction of "descriptors", which enable computed properties. For compatibility reasons, classes are still old-style by default. New-style classes are created by specifying another new-style class (i.e. a type) as a parent class, or the "top-level type" object if no other parent is needed. The behaviour of new-style classes differs from that of old-style classes in a number of important details in addition to what type returns. Some of these changes are fundamental to the new object model, like the way special methods are invoked. Others are "fixes" that could not be implemented before for compatibility concerns, like the method resolution order in case of multiple inheritance. Python 3 only has new-style classes. No matter if you subclass from object or not, classes are new-style in Python 3.
其他回答
Guido写了关于新型类的内幕,这是一篇关于Python中的新型和老式类的很棒的文章。
Python 3只有new-style类。即使你写了一个“老式类”,它也是隐式地从object派生的。
新型类具有一些老式类所缺乏的高级特性,如super,新的C3 mro,一些神奇的方法等。
这里有一个非常实际的真/假的区别。以下代码的两个版本之间的唯一区别是,在第二个版本中,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> >>>
新的样式类可以使用super(Foo, self),其中Foo是类,self是实例。
超级(类型、对象或者类型) 返回一个代理对象,该对象将方法调用委托给类型的父类或兄弟类。这对于访问在类中被重写的继承方法非常有用。除了类型本身被跳过之外,搜索顺序与getattr()所使用的相同。
在Python 3中。X你可以简单地在类中使用super()而不带任何参数。
对于属性查找,旧样式的类仍然稍微快一些。这通常并不重要,但在性能敏感的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
Declaration-wise:
New-style类继承自object或另一个New-style类。
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
老式的类没有。
class OldStyleClass():
pass
注意事项:
Python 3不支持旧样式的类,所以上面提到的任何一种形式都会产生新样式的类。
推荐文章
- 将Pandas或Numpy Nan替换为None以用于MysqlDB
- 使用pandas对同一列进行多个聚合
- 使用Python解析HTML
- django MultiValueDictKeyError错误,我如何处理它
- 如何在for循环期间修改列表条目?
- 我如何在Django中创建一个鼻涕虫?
- 合并两个PHP对象的最佳方法是什么?
- 没有名为'django.core.urlresolvers'的模块
- 蟒蛇导出环境文件
- Django - makemigrations -未检测到任何更改
- SQLAlchemy:引擎、连接和会话差异
- 在Python Pandas中删除多个列中的所有重复行
- 更改pandas DataFrame中的特定列名
- 将Pandas多索引转换为列
- 熊猫在每组中获得最高的n个记录