面向对象_新式类与经典类

  在python2中,没有显式继承object的类以及该类的子类,都是经典类。显示的声明继承object的类以及该类的子类都是新式类。在python3中,无论是否继承object,都默认继承object,即python3中的所有类均为新式类

  __new__

  新式类新增了__new__方法,它的原型是object.__new__(cls,[,.....])。cls是一个类对象,当你调用C(*args,**kwargs)来创建一个类C的实例时,python内部调用的是C.__new__(C,*args,**kwargs),然后返回是类C的实例c,在确认c是C的实例后,python再调用C.__init__(C,*args,**kwargs)来初始化实例c。

class Person():

    def __new__(cls, name,age):
        print('__new__ called')
        return super(Person,cls).__new__(cls)

    def __init__(self,name,age):
        print('__init__ called')
        self.name = name
        self.age = age

    def __str__(self):
        return ('123')

p1 = Person('lary',18)
print(p1)

  __slots__

  新式类具有__slots__属性,该属性会对生成子类实例产生影响。当类C中有比较少的变量,而且拥有__slots__属性时,类C的实例就没有__dict__属性,而是把变量值存在一个固定的地方。__slots__属性虽然令实例失去了绑定任意属性的遍历,但是因为每一个实例没有__dict__属性,却能有效减少每一个实例消耗的内存,有利于生成小而精干的实例。

  __getattirbute__

  对新式类的实例来说,所有属性和方法的访问都是通过__getattribute完成。这是由object基类实现的。

class animal(object):

    def __getattribute__(self, item):
       return object.__getattribute__(self,item)()

    def eat(self):
        print('eating...')

#print(animal.__dict__)
cat = animal()
#print(cat.__dict__)
cat.eat
# #当获取属性时,直接return object.__getattribute__(self,*args,**kwargs)
# #如果需要获取某个方法的返回值时,则需要在函数后面加上一个()即可,如果不加的话,返回的是函数引用地址
# #在__getattribute__方法里面,不能用self.xxx这种方式调用。因为调用类的属性每次都会强制调用__getattribute__,所以会导致递归调用

  实例方法的调用

  在经典对象模型中,无论是显式调用还是隐式调用特殊方法,都会调用实例中后绑定的特殊方法。而在新的对象模型中,除非显式的调用实例的特殊方法,否则python总是会去调用类中定义的特殊方法,如果没有定义的话就报错。

def getItem(index):
    return index + 1

class C():
    pass

c = C()
c.__getitem__ = getItem
print(c[1])             #隐式访问报错

print(c.__getitem__(1)) #显示访问成功

  多继承

  新式类同样支持多继承,但是如果新式类想要从多个内置类型中生成一个新类的话,则这些内置类必须是经过精心设计,能够互相兼容的。

  mro

  在经典对象模型中,方法和属性的查找链遵循深度优先。而在新式类中,对象模型方法和属性的查找遵循广度优先。

  super方法

  当你使用super()函数时,python会在mro列表上继续搜索下一个类,只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个mro列表,每个地方也只会被调用一次。

class Base:
    def __init__(self):
        print('Base.__init__')

class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')

class B(Base):
    def __init__(self):
        super().__init__()
        print('B.__init__')

class C(A,B):
    def __init__(self):
        super().__init__()  # Only one call to super() here
        print('C.__init__')

c = C()

  属性装饰器

  经典类具有一种@property装饰器,而新式类具有三种属性装饰器

   @property
    def price(self):
        print ('@property')

    @price.setter
    def price(self, value):
        print ('@price.setter')

    @price.deleter
    def price(self):
        print ('@price.deleter')

obj = C()
obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
del obj.price      # 自动执行 @price.deleter 修饰的 price 方法

 

posted @ 2018-11-21 10:38  日新其德止于至善  阅读(136)  评论(0编辑  收藏  举报