Python Self关键字

Python Self关键字

self代表类的实例。我们可以使用 “self “关键字访问Python中类的属性和方法。这个关键字将属性与所提供的类的参数联系起来。

由于 Python 没有采用 @ 语法来创建对实例属性的引用,我们必须使用 self。Python 选择了实现方法,以便自动提供方法所对应的类的实例,但不是立即接收:任何方法的第一个参数都是执行该方法的实例。

代码

# Python program to show the use of the self keyword

class Class: 
    def __init__(self): 
        print("The reference id of the self method is: ",id(self)) 

# Creating an instance of the class
obj = Class() 
print("The reference id of the object is: ",id(obj))

输出

The reference id of the self method is:  139904481668400
The reference id of the object is:  139904481668400 

可以看出,self和obj指的是一个内存位置。

为什么每次都要定义self方法

尽管我们了解self的目的,但它可能显得很奇怪,特别是对那些学习过其他编程语言的开发者来说,每次构造方法时都明确地将self作为参数提供。人们相信,显式总是比隐式好。

那么,我们为什么要这样做呢?首先,考虑一个基本的例子。我们有一个Position类,它有一个叫做distance的方法,用于计算给定点与原点的距离。

代码

# Python program to create a class having a method called distance

class Distance(object):
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y

    def distance(self):
        """Finding the distance of point_ from the origin"""
        return (self.x**2 + self.y**2) ** 0.5

让我们通过创建一个类的实例来使用这个类来计算距离。

代码

# Python program to calculate the distance using the class Distance

class Distance(object):
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y

    def distance(self):
        """Finding the distance of point_ from the origin"""
        return (self.x**2 + self.y**2) ** 0.5

object_ = Distance(3, 4)
dist = object_.distance()
print("The distance of the point (3, 4) from the origin is: ", dist)

输出

The distance of the point (3, 4) from the origin is:  5.0

在上面的情况中,__init__()声明了三个参数,但我们只传递了两个参数(3和4)。同样地,distance()需要一个输入,但没有收到一个。为什么 Python 解释器没有报告不匹配的参数号?

代码

# Python program to calculate the distance using the class Distance

class Student(): 

    # calling the __init__ method or constructor 
    def __init__(self, name, age): 
        self.name = name 
        self.age = age 

    def details(self): 
        print("The name of the student is", self.name ) 
        print("The age of the student is", self.age ) 

# both the objects, Harry and Louis, have their own self arguments, which contain their distinct attributes 
Harry = Student("Harry", 29) 
Louis = Student("Louis", 30) 

# Using the method details
Harry.details() # This will show same output as Studnet.details(Harry) 
Louis.details()  # This will show same output as Studnet.details(Louis) 

# We can also execute the following commands 
print("The age of Harry is ",Harry.age) 
print("The age of Louis is ",Louis.age)

输出

The name of the student is Harry
The age of the student is 29
Name of the student is Louis
Age of the student is 30
The age of Harry is  29
The age of Louis is  30 

出现这种情况是因为在函数 Object() { [native code] } 中分配了属性之后,它们就与那个特定的对象相关联了;在这个例子中,当我们初始化对象(Harry 和 Louis)时,属性(名字、年龄)被附加到了对象上。

Python 在每次调用实例函数时都会提供实例,比如名字,在幕后。

self参数必须作为第一个参数被送到实例函数和构造函数中。如果我们不给它,会导致错误。

代码

# Python program to show that the self argument is always the first argument 

# Creating a class
class Paint: 
    def __init__(): 
        print("This command is inside the constructor") 

# Creating an instance of the class
object_ = Paint() 
print("This command shows the instance is created") 

输出

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
 in 
      7 
      8 # Creating an instance of the class
----> 9 object_ = Paint()
     10 print("This command shows the instance is created")
     11 

TypeError: __init__() takes 0 positional arguments but 1 was given

在实例方法中,self是一个参数,其名称可以用任何其他参数名称代替。然而,建议使用self,因为它可以提高代码的清晰度,也是优秀的编程实践。

代码

# Python program to show that the self parameter can have a different name in the Instance Method

# Creating a class
class Class: 
    # Creating an Instance Method with a different keyword than self
    def __init__(changed_self):  
        print("We have used another name for the self parameter")  

# creating an instance of the class         
object_ = Class()

输出

We have used another name for the self parameter

如何避免self参数

我们现在可以看到,类对象或实例本身被自动作为第一个参数给了。当创建一个静态方法时,这种隐含的行为可以被阻止。请看下面这个基本的例子。

代码

# Python program to show how to avoid the self parameter by creating a static method

# Creating a class
class Class(object):
    # Creating a static method
    @staticmethod

    # Creating a method without the self keyword
    def without_self():
        print("We did not pass the self parameter to this method")

# Creating an instance of the class and calling the method without_self
instance = Class()
instance.without_self()

输出

We did not pass the self parameter to this method

@staticmethod 是一个 Python 内置的函数装饰器,在这里,它使 without_self() 成为静态的。当我们调用这个方法时,这个函数被调用。

我们可以从前面的案例中看出,在使用静态方法时,可以避免将类的实例作为第一个参数的隐含行为。静态方法的表现与普通的 Python 函数类似 (它将把所有的类方法转换为静态方法)。

代码

# Python program to check the type of the instance method
print(type(instance.without_self))

输出

<class 'function'>

__init__()不是一个构造函数

__init__() 函数不是构造函数,这是从信息中得出的一个重要结论。许多没有经验的 Python 程序员对此感到困惑,因为 __init__() 是在我们构建一个对象时执行的。

正如我们所知,实例本身是__init__() 方法的第一个参数。方法__init__()是用来在构建对象后立即初始化它的。

用技术术语来说,函数Object()是一个构建对象本身的方法。这个函数在 Python 中被称为 new ()。这个方法的语法是。

语法

__new__(cls, *args, **kwargs)

当调用 __new__() 方法时,类本身会被自动提供为第一个参数 (cls)。

cls,像self一样,只是一个命名惯例。此外,*args**kwargs 参数在 Python 函数调用中被利用来接受任意数量的参数。

在实现 __new__() 时,请记住以下几点。

  • __new__() 总是在 __init__() 之前执行。
  • 第一个参数是类的名字,它是隐含的。
  • __new__() 应该总是返回一个合法的对象。它不是必需的,但它的主要功能是构造并返回一个 Python 对象。

考虑一下下面的例子。

代码

# Python program to show how to use the __new__() method in a class

# Creating a class
class Class(object):

    # Creating the __new__() method before the __init__() method
    def __new__(cls, *args, **kwargs):
        print("This is under the new method")
        print("The class argument: ", cls)
        print("The args: ", args)
        print("The kwargs: ", kwargs)

        # Creating an object of the class and returning that object as required by the __new__() method
        object_ = super().__new__(cls)
        return object_

    # Creating the __init__() method
    def __init__(self, a = 0, b = 0):
        print("This is under the init method")
        self.a = a
        self.b = b

# Calling the class
c = Class(3,4)

输出

This is under the new method
The class argument:  <class '__main__.Class'>
The args:  (3, 4)
The kwargs:  {}
This is under the init method

这个场景显示了 __new__() 是如何在 __init__() 之前被调用的。我们也可以观察到,类被作为一个参数发送到 __new__() (点) 。最后,对象是使用对象基类的__new__() 函数形成的。

在 Python 中,基类,即所有后续类都是从它派生出来的类,就是对象。在前面的例子中,我们用super()来做这件事。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程