在Python中从子方法调用父方法时,为什么要使用self关键字?

时间:2019-08-10 19:24:02

标签: python oop overriding self

为什么从子方法调用父方法时需要使用self关键字作为参数?

让我举个例子


class Account:

     def __init__(self,filepath):
         self.filepath = filepath
         with open(self.filepath,"r") as file:
              self.blanace = int(file.read())

     def withDraw(self,amount):
          self.blanace = self.blanace - amount
          self.commit()

     def deposite(self,amount):
          self.blanace = self.blanace + amount
          self.commit()


     def commit(self):
          with open(self.filepath,"w") as file:
               file.write(str(self.blanace))



class Checking(Account):

      def __init__(self,filepath):
           Account.__init__(sellf,filepath) ######## I'm asking about this line.

关于此代码,

我知道声明一个新对象时,self会自动传递给类,所以

我希望当我声明新对象时,python会设置self =已声明的对象,因此现在self关键字将在“' init '”子方法中可用,因此无需编写再次像

一样手动
Account.__init__(sellf,filepath) ######## I'm asking about this line.

2 个答案:

答案 0 :(得分:4)

所有实例方法都是function值的类属性。如果通过实例访问属性,则某些幕后的“魔术”(称为描述符协议)会负责将foo.bar()更改为type(foo).bar(foo)__init__本身也只是另一种实例方法,尽管通常只在覆盖孩子中的__init__时才显式调用它。

在您的示例中,您正在通过类显式调用父类的__init__方法,因此必须显式传递selfself.__init__(filepath)将导致无限递归)。

避免这种情况的一种方法是显式地引用父类,而是让代理为您确定“最接近的”父类。

 super().__init__(filepath)

这里有一些魔术:super(不带参数)在Python实现的帮助下确定它静态出现在哪个类中(在这种情况下为Checking),并将其与self,作为super的隐式参数。在Python 2中,您始终必须明确:super(Checking, self).__init__(filepath)。 (在Python 3中,您仍然可以显式传递参数,因为有一些用例(尽管很少见)可用于传递当前静态类和self以外的参数。super(SomeClass)最常见的是不是self作为隐式第二个参数,并处理类级代理。)


具体来说,function类定义了__get__方法;如果属性查找的结果定义了__get__,则将返回该方法的返回值,而不是属性值本身。换句话说,

foo.bar

成为

foo.__dict__['bar'].__get__(foo, type(foo))

,该返回值是method类型的对象。调用method实例只会导致调用原始函数,其第一个参数是__get__作为其第一个参数的实例,而其余参数则是传递给原始方法的任何其他参数打电话。

答案 1 :(得分:1)

一般来说,我会将此数字累计到the Zen of Python,具体来说,是以下声明:

  1. 显式优于隐式。
  2. 可读性计数。
  3. 面对歧义,拒绝猜测的诱惑。

...等等。

这是Python的口头禅-以及许多其他情况,这似乎是多余的并且过于简单化,但是明确表示是Python的关键“目标”之一。也许另一个用户可以给出更多的 explicit 示例,但是在这种情况下,我要说的是,不要在一个调用中明确定义参数,然后消失,这很有意义-在查看时可能会使事情变得不清楚子功能,而无需同时查看其父功能。

相关问题