为什么从子方法调用父方法时需要使用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.
答案 0 :(得分:4)
所有实例方法都是function
值的类属性。如果通过实例访问属性,则某些幕后的“魔术”(称为描述符协议)会负责将foo.bar()
更改为type(foo).bar(foo)
。 __init__
本身也只是另一种实例方法,尽管通常只在覆盖孩子中的__init__
时才显式调用它。
在您的示例中,您正在通过类显式调用父类的__init__
方法,因此必须显式传递self
(self.__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,具体来说,是以下声明:
...等等。
这是Python的口头禅-以及许多其他情况,这似乎是多余的并且过于简单化,但是明确表示是Python的关键“目标”之一。也许另一个用户可以给出更多的 explicit 示例,但是在这种情况下,我要说的是,不要在一个调用中明确定义参数,然后消失,这很有意义-在查看时可能会使事情变得不清楚子功能,而无需同时查看其父功能。