Python从入坑到入土-001-类相关

本文介绍了Python中类构造的三个关键函数:__init__用于实例初始化,__new__控制实例化过程,super则确保正确调用基类方法。通过具体代码示例展示了这些函数如何工作及其在继承中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在编写类时经常会用到的三个函数__init__,__new__,super()。下面就简要阐述下这三个函数的用法。

1:__init__

__init__的方法一般都是用在初始化一个类的实例时候。如下

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

class Person(object):
    """Silly Person"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)

if __name__ == '__main__':
    piglei = Person('piglei', 24)
    print piglei

__init__在初始化person实例的时候,需要传入两个值:name,age。并对实例self中的name,age进行赋值。(self表示实例化的对象)

2:__new__

__new__接受参数的形式和__init__时一样的,但是__new__是作用在创建实例的时候,__init__是创建完实例以后,对实例进行数据初始化的时候起作用的。

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

class Person(object):
    """Silly Person"""

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

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

    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)

if __name__ == '__main__':
    piglei = Person('piglei', 24)
    print piglei

执行结果是

piglei@macbook-pro:blog$ python new_and_init.py
__new__ called.
__init__ called.
<Person: piglei(24)>
__new__先被执行,__init__后被执行。__new__会返回这个类的实例,它控制了一个类的实例化过程。

super()

在类的继承中,使用该函数可以直接调用父类中的方法,而不用担心方法会被覆盖。如下

class Animal(object):
    def __init__(self, name):
        self.name = name
    def greet(self):
        print 'Hello, I am %s.' % self.name

class Dog(Animal):
    def greet(self):
        super(Dog, self).greet()   # Python3 可使用 super().greet()
        print 'WangWang...'

Animal是Dog的父类,在Dog的方法同名方法greet中可以直接通过super来调用父类中的方法。其中super比较常见的用法是在__init__初始化时使用。

class Base(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

class A(Base):
    def __init__(self, a, b, c):
        super(A, self).__init__(a, b)  # Python3 可使用 super().__init__(a, b)
        self.c = c

深入super()

其实super和父类没有实质性的联系,是通过MRO(Method Resolution on Order)列表来进行关联的,MRO表示了类继承的顺序。

class Base(object):
    def __init__(self):
        print "enter Base"
        print "leave Base"

class A(Base):
    def __init__(self):
        print "enter A"
        super(A, self).__init__()
        print "leave A"

class B(Base):
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"

class C(A, B):
    def __init__(self):
        print "enter C"
        super(C, self).__init__()
        print "leave C"

其中类C继承了A,B两个类,A,B都继承了Base类。

      Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C

实例化结果

>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C

为什么在enter A后不是enter Base,而是enter B。下面我们通过MRO函数来看下类C的继承关系。

>>> C.mro()   # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]

MRO函数显示出的继承关系,就是类C的实际继承效果。

super的工作原理如下

def super(cls, inst):
    mro = inst.__class__.mro()
    return mro[mro.index(cls) + 1]

其中cls代表类,inst代表实例。

上面的代码做了两件事,获得实例inst的类的MRO列表,return返回MRO列表中的当前类的下一个类。所以是MRO控制了类和父类之间的跳转,而不是super调用了父类。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值