Python Self关键字
self代表类的实例。我们可以使用 “self “关键字访问Python中类的属性和方法。这个关键字将属性与所提供的类的参数联系起来。
由于 Python 没有采用 @ 语法来创建对实例属性的引用,我们必须使用 self。Python 选择了实现方法,以便自动提供方法所对应的类的实例,但不是立即接收:任何方法的第一个参数都是执行该方法的实例。
代码
输出
可以看出,self和obj指的是一个内存位置。
为什么每次都要定义self方法
尽管我们了解self的目的,但它可能显得很奇怪,特别是对那些学习过其他编程语言的开发者来说,每次构造方法时都明确地将self作为参数提供。人们相信,显式总是比隐式好。
那么,我们为什么要这样做呢?首先,考虑一个基本的例子。我们有一个Position类,它有一个叫做distance的方法,用于计算给定点与原点的距离。
代码
让我们通过创建一个类的实例来使用这个类来计算距离。
代码
输出
在上面的情况中,__init__()
声明了三个参数,但我们只传递了两个参数(3和4)。同样地,distance()需要一个输入,但没有收到一个。为什么 Python 解释器没有报告不匹配的参数号?
代码
输出
出现这种情况是因为在函数 Object() { [native code] } 中分配了属性之后,它们就与那个特定的对象相关联了;在这个例子中,当我们初始化对象(Harry 和 Louis)时,属性(名字、年龄)被附加到了对象上。
Python 在每次调用实例函数时都会提供实例,比如名字,在幕后。
self参数必须作为第一个参数被送到实例函数和构造函数中。如果我们不给它,会导致错误。
代码
输出
在实例方法中,self是一个参数,其名称可以用任何其他参数名称代替。然而,建议使用self,因为它可以提高代码的清晰度,也是优秀的编程实践。
代码
输出
如何避免self参数
我们现在可以看到,类对象或实例本身被自动作为第一个参数给了。当创建一个静态方法时,这种隐含的行为可以被阻止。请看下面这个基本的例子。
代码
输出
@staticmethod 是一个 Python 内置的函数装饰器,在这里,它使 without_self() 成为静态的。当我们调用这个方法时,这个函数被调用。
我们可以从前面的案例中看出,在使用静态方法时,可以避免将类的实例作为第一个参数的隐含行为。静态方法的表现与普通的 Python 函数类似 (它将把所有的类方法转换为静态方法)。
代码
输出
__init__()
不是一个构造函数
__init__()
函数不是构造函数,这是从信息中得出的一个重要结论。许多没有经验的 Python 程序员对此感到困惑,因为 __init__()
是在我们构建一个对象时执行的。
正如我们所知,实例本身是__init__()
方法的第一个参数。方法__init__()
是用来在构建对象后立即初始化它的。
用技术术语来说,函数Object()是一个构建对象本身的方法。这个函数在 Python 中被称为 new ()。这个方法的语法是。
语法
当调用 __new__()
方法时,类本身会被自动提供为第一个参数 (cls)。
cls,像self一样,只是一个命名惯例。此外,*args
和 **kwargs
参数在 Python 函数调用中被利用来接受任意数量的参数。
在实现 __new__()
时,请记住以下几点。
__new__()
总是在__init__()
之前执行。- 第一个参数是类的名字,它是隐含的。
__new__()
应该总是返回一个合法的对象。它不是必需的,但它的主要功能是构造并返回一个 Python 对象。
考虑一下下面的例子。
代码
输出
这个场景显示了 __new__()
是如何在 __init__()
之前被调用的。我们也可以观察到,类被作为一个参数发送到 __new__()
(点) 。最后,对象是使用对象基类的__new__()
函数形成的。
在 Python 中,基类,即所有后续类都是从它派生出来的类,就是对象。在前面的例子中,我们用super()来做这件事。