其实是看到了__new__,然后衍生出了下面一系列东西。在此做一个总结。
首先说明python3.x都是新式类。
2.2开始Python引入了新式类,在2.x的版本中。新式类和经典类的主要区别是是否显式继承object。因为我用3.x这里只用2.7演示经典类(就是不继承object的类)。
为什么还要区分下新式类和经典类,主要还是对我们弄清楚python有帮助。
主要区别:
1.新式类可以通过__class__属性获取自身的类型:type
class NewStyle:
pass
style = NewStyle()
print(style)
print(type(style))
print(style.__class__)
在2.7的返回
<__main__.NewStyle instance at 0x7fce524ab290>
<type 'instance'>
__main__.NewStyle
在3.6的返回
<__main__.NewStyle object at 0x7fc4ffddca58>
<class '__main__.NewStyle'>
<class '__main__.NewStyle'>
3.6中type和__class__是一致的
2.继承搜索顺序不同,在经典类先深入继承树左侧,再返回,开始找右侧;新式类先水平搜索,再向下。
class root:
def __init__(self):
pass
def get_class(self):
print('root')
class p1(root):
def __init__(self):
pass
class p2(root):
def __init__(self):
pass
def get_class(self):
print('p2')
class s(p1,p2):
pass
s().get_class()
3.6返回p2,2.7返回root
注意,需要相同的root才出现广度优先,如果root不同则肯定是走到root才返回的。
3.新式类增加了__slots__内置属性,可以把实例属性的种类锁定到__slots__规定的范围中,slots范围外的就不能自动添加了,减轻内存负担。
class SlotsTest:
__slots__ = ('name', 'age')
test = SlotsTest()
test.name = "slots1"
print(test.name)
test.name1 = "slots2"
print(test.name1)
3.6运行报错
slots1
Traceback (most recent call last):
File "test.py", line 42, in <module>
test.name1 = "slots2"
AttributeError: 'SlotsTest' object has no attribute 'name1'
2.7运行正常
slots1
slots2
4.新式类可以使用__getattribute__方法
class GetAttrTest:
def __getattribute__(self, *args, **kwargs):
print("GetAttrTest.__getattribute__")
test = GetAttrTest()
test.test
3.6运行正常
GetAttrTest.__getattribute__
2.7运行报错
Traceback (most recent call last):
File "test.py", line 49, in <module>
test.test
任何通过实例访问属性都会触发__getattribute__