Python 新式类和经典类(老式类)的区别

前言

  • 从Python2.2开始,Python 引入了 new style class(新式类)
  • Python 2.x中默认都是经典类,只有显式继承了object才是新式类
  • Python 3.x中默认都是新式类,不必显式的继承object

1、新式类对象可以直接通过__class__属性获取自身类型:type

# coding:utf8


class A:
    # 经典类
    pass


class A1(object):
    # 新式类
    pass


a = A()
print "经典类"
print a
print type(a)
print a.__class__

print "新式类"
a1 = A1()
print a1
print type(a1)
print a1.__class__

输出:

经典类
<__main__.A instance at 0x1038ba368>
<type 'instance'>
__main__.A

新式类
<__main__.A1 object at 0x102d49e90>
<class '__main__.A1'>
<class '__main__.A1'>

E1是定义的新式类,那么输输出a1的时候,不论是type(a1),还是a1.__class__都是输出的<class '__main__.A1'>,保持了class与type的统一;

2、对于多重继承的属性搜索顺序不一样

新式类是采用C3 MRO的算法处理多继承的(简单理解为 广度优先搜索,但不完全是),旧式类采用深度优先搜索

class A():
    def __init__(self):
        pass
    def save(self):
        print "This is from A"
class B(A):
    def __init__(self):
        pass
class C(A):
    def __init__(self):
        pass
    def save(self):
        print  "This is from C"
class D(B,C):
    def __init__(self):
        pass
        
fun =  D()
fun.save()

经典类的答案: This is from A
新式类的答案: This is from C

3、新式类增加了__slots__内置属性, 可以把实例属性的种类锁定到__slots__规定的范围之中

# -*- coding:utf-8 -*-

class A():
    __slots__ = ('name', 'age')


class A1(object):
    __slots__ = ('name', 'age')


a = A()
a1 = A1()

a.name = "a_name"
print a.name
a.name1 = "a_name1"
print a.name1
# a.name1 = "a"

a1.name = "a1_name"
print a1.name
a1.name1 = "a1_name1"
print a1.name1


输出:
a_name
a_name1
a1_name
  File "xxx/new_old_class.py", line 21, in <module>
    a1.name1 = "a1_name1"
AttributeError: 'A1' object has no attribute 'name1'

A1是新式类添加了__slots__ 属性,所以只允许添加name age,所以a1.name1是会出错的;

A经典类__slots__ 属性没用,所以a.name1没有问题。

通常每一个实例都会有一个__dict__属性,用来记录实例中所有的属性和方法,也是通过这个字典,可以让实例绑定任意的属性;

而__slots__属性作用就是,当类C有比较少的变量,而且拥有__slots__属性时,类C的实例 就没有__dict__属性,而是把变量的值存在一个固定的地方。如果试图访问一个__slots__中没有的属性,实例就会报错。

这样操作有什么好处呢?__slots__属性虽然令实例失去了绑定任意属性的便利,但是因为每一个实例没有__dict__属性,却能有效节省每一个实例的内存消耗,有利于生成小而精干的实例。

4、新式类增加了__getattribute__方法

# -*- coding:utf-8 -*-


class A():
    def __getattribute__(self, *args, **kwargs):
        print "A.__getattribute__"


class A1(object):
    def __getattribute__(self, *args, **kwargs):
        print "A1.__getattribute__"


a = A()
a1 = A1()


a1.test
print "------"
a.test

输出:
A1.__getattribute__
Traceback (most recent call last):
------
  File "xxx/new_old_class.py", line 20, in <module>
    a.test
AttributeError: A instance has no attribute 'test'

可以看出A1是新式类,每次通过实例访问属性,都会经过__getattribute__函数;

A不会调用__getattribute__所以出错了

参考:

https://www.zhihu.com/question/22475395
https://blog.csdn.net/u010066807/article/details/46896835

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值