关于Python Self的权威指南
如果您很久以前开始进行Python编程,那么您会遇到“自我”一词。每当您使用Python进行面向对象的编程时,自我就会遇到您。您已经在方法定义和变量初始化中看到了。但是,在深入自我之前,让我们了解什么是类和实例变量以及什么是类和实例方法。
Python中的类变量
类变量是与该类的所有实例共享的变量的类型。这意味着,如果您要从实例访问类变量,则该值将相同。类变量是在类定义之后且在任何方法或函数之外定义的。
class MyClass: var_1 = "COVID_19" var_2 = 100 var_3 = False
在此代码中,var_1,var_2和var_3是类变量。
Python中的实例变量
实例变量是所有实例都保留在其中的变量类型(即,特定对象拥有其实例变量)。因此实例变量的值因实例而异。
class MyClass: var_1 = "COVID_19" var_2 = 100 var_3 = False def __init__(self, param1, param2): self.instance_var1 = param1 # instance_var1 is a instance variable self.instance_var2 = param2 # instance_var2 is a instance variable
在此代码中,实例变量是instace_var1和instance_var2。
与类变量不同,实例变量应在方法内定义。
class MyClass: var_1 = "COVID_19" var_2 = 100 var_3 = False def __init__(self, param1, param2, param3): self.instance_var1 = param1 # instance_var1 is a instance variable self.instance_var2 = param2 # instance_var2 is a instance variable self.instance_var3 = param3 # instance_var3 is a instance variable obj1 = MyClass('Disease', 150, True) print('The class variable is: ', obj1.var_1) print('The instance variable is: ', obj1.instance_var1) obj2 = MyClass('Rasparatory', 200, False) print('The class variable is: ', obj2.var_1) print('The instance variable is: ', obj2.instance_var2)
在此示例中,我们定义了三个类变量和三个实例变量。
然后,我们创建了两个实例,分别称为obj1和obj2。
现在,如果使用obj1和obj2访问类变量,则值将相同。在我们的示例中,我们可以使用不同的实例访问var_1和var_2,并且值与您在输出中看到的相同。
但是当我们使用不同的实例访问实例变量时,值是不同的。这是因为在实例化时,我们是通过__init __()方法提供值的,因此实例之间的值是不同的。
Python中的类方法
类方法对于设置或获取类的详细信息(状态)很有用。类方法具有应作为第一个参数放置的特定参数。这是一个cls参数,代表类。
class MyClass: var_1 = "COVID_19" var_2 = 100 var_3 = False @classmethod def class_method(cls): print("the class method was called") return 1 print(MyClass.class_method()) print(MyClass.var_1) print(MyClass.var_2) print(MyClass.var_3)
在此示例中,我们使用@classmethod装饰器定义了类方法。这里的类方法是class_method,它以cls作为参数。创建实例方法时,它与self相同。
因此,当我们定义类方法时,将cls作为第一个参数传递,而当我们定义实例方法时,则将self作为第一个参数传递。
然后,我们仅使用类而非对象访问了类方法。我们还使用class访问了class变量。因此,即使不实例化对象,我们也可以按以下方式访问类方法。
MyClass.class_method()
因此,这就是您可以在Python中定义和访问类方法的方式。
Python中的实例方法
好的,我们已经看到了实例变量,类变量和类方法。现在,我们将看到实例方法。
定义实例方法时,方法的第一个参数应始终为self。但是,您可以随心所欲地为它命名,而不必为自己命名,但是该参数表示的含义将始终相同。这是一个坚持自我的更好主意,因为这是全球惯例。
class MyClass: def add(self, a, b): return a + b obj = MyClass() print(obj.add(11, 21))
在此示例中,我们定义了一个名为add()的实例方法,它带有两个参数。
然后我们实例化了一个对象并调用了add()方法。
从上面的代码中您可以注意到,尽管在定义实例方法时,第一个参数是self。当我们调用该方法时,我们不会为自己传递任何东西作为参数。
Python中的自我是什么
self关键字用于表示给定类的实例(对象)。在上述情况下,obj对象具有其自己的a和b属性。如果没有自变量,则同一类不能包含有关该对象的信息。
但是,由于类是一个蓝图,因此self允许访问Python中每个对象的属性和方法。这使每个对象都有其属性和方法。这就是为什么甚至在创建这些对象之前,我们在定义类时就将这些对象引用为self的原因。
明确定义自己
即使我们知道self的用法,这似乎也很奇怪,特别是对于来自其他编程语言的程序员而言,每次定义实例方法时,self都会作为参数显式传递。
class MyClass: def __init__(self, a, b): self.a = a self.b = b def multi(self): return self.a * self.b obj = MyClass(3, 7) print('The multiplication of a and b is: ', obj.multi())
如果运行上面的代码,您将获得以下输出。
The multiplication of a and b is: 21
在上面的示例中,__init __()定义了三个参数,但我们仅传递了两个参数(3和7)。同样,multi()函数需要一个,但是在调用obj.multi()函数时传递了零个参数。为什么这不会给出错误?
引擎盖下会发生什么
当我们使用某些参数调用实例方法时,相关类函数会通过将方法的对象放在第一个参数之前来调用。因此,像obj.multi(args)之类的东西都会变成Class.multi(obj,args)。调用过程是自动的,而接收过程不是(它的显式)。
这是在类中函数的第一个参数必须是对象本身的主要原因。将此参数写为self纯粹是一种约定。它不是关键字,在Python中没有特殊含义。我们可以使用其他名称,但不建议使用。大多数人都不喜欢使用self以外的名称,这会降低代码的可读性。
到目前为止,您已经很清楚,对象(实例)本身是作为第一个参数自动传递的。进行静态方法时可以避免隐式行为。我们已经在本文前面看到了类方法。
显式自我并不是Python独有的。这个想法是从Modula-3借来的。
Python __init __()
在Python中,__init __()方法不是构造函数。由于创建对象时调用__init __(),许多坦诚的程序员对此感到困惑。
如果仔细检查,您会发现__init __()中的第一个参数是对象本身(对象已经存在)。函数__init __()在创建对象后直接调用,并用于对其进行初始化。从技术上讲,构造函数是一种使对象本身成为对象的方法。在Python中,此方法是__new __()。此方法的典型签名如下。
__new__(cls, *args, **kwargs)
调用__new __()方法时,类本身将作为第一个参数自动传递(cls)。
同样,就像自己一样,cls只是一个命名约定。此外,* args和** kwargs用于在Python函数调用期间获取任意数量的参数。
在实现__new __()时要记住一些有意义的事情:
- 总是在__init __()之前调用__new __()。
- 第一个参数是类本身,它是隐式传递的。
- 始终从__new __()返回有效对象。不是强制性的,但其主要用途是创建和返回对象。
请参阅以下代码。
class MyClass: def __new__(cls, *args, **kwargs): print("__NEW__") print(cls) print(args) print(kwargs) # create our object and return it obj = super().__new__(cls) return obj def __init__(self, a, b): self.a = a self.b = b def multi(self): return self.a * self.b obj = MyClass(3, 7) print('The multiplication of a and b is: ', obj.multi())
输出量
__NEW__(3, 7) {} The multiplication of a and b is: 21
此示例说明__new __()在__init __()之前被调用。我们还可以看到__new __()中的参数cls是类本身(点)。
最后,通过在对象基类上调用__new __()方法来创建对象。
在Python中,对象是派生所有其他类的基类。在上面的代码中,我们使用super()完成了此操作。
结论
现在您了解了为什么应该始终将self用作Python中实例方法的第一个参数,以及当我们调用实例方法时幕后发生的事情。我们已经看到了类和实例变量,类和实例方法,自我,为什么我们使用自我,自我命名约定。
Python本身就是这样。