想想这个例子:
class MyClass:
def func(self, name):
self.name = name
我知道self引用MyClass的特定实例。但是为什么func必须显式地包含self作为参数呢?为什么我们需要在方法的代码中使用self ?其他一些语言将其隐式化,或者使用特殊的语法。
有关设计决策的语言无关性考虑,请参见强制显式使用this/self指针的好处是什么?
要关闭OP省略方法的self形参并获得TypeError的调试问题,请使用TypeError: method()接受1个位置参数,但给出了2个。如果OP省略了self。在方法体中得到一个NameError,考虑如何在类中调用函数?
因为按照python的设计,其他的选择几乎行不通。Python被设计为允许在隐式this (a-la Java/ c++)或显式@ (a-la ruby)都不能工作的上下文中定义方法或函数。让我们看一个带有python约定的显式方法的例子:
def fubar(x):
self.x = x
class C:
frob = fubar
现在fubar函数不能工作了,因为它假定self是一个全局变量(在frob中也是如此)。另一种方法是使用替换的全局作用域(其中self是对象)执行方法。
隐式方法是
def fubar(x)
myX = x
class C:
frob = fubar
这意味着myX将被解释为fubar(以及frob)中的局部变量。这里的替代方案是使用替换的局部作用域执行方法,该作用域在调用之间保留,但这将消除方法局部变量的可能性。
然而,目前的情况很好:
def fubar(self, x)
self.x = x
class C:
frob = fubar
在这里,当作为方法调用时,frob将通过self参数接收它所调用的对象,fubar仍然可以以对象作为参数调用并且工作相同(我认为它与C.frob相同)。
与Java或c++不同,Python不是为面向对象编程而构建的语言。
在Python中调用静态方法时,只需编写一个内部带有常规参数的方法。
class Animal():
def staticMethod():
print "This is a static method"
然而,一个对象方法,它需要你创建一个变量,在这里是Animal,它需要self参数
class Animal():
def objectMethod(self):
print "This is an object method which needs an instance of a class"
self方法还用于引用类中的变量字段。
class Animal():
#animalName made in constructor
def Animal(self):
self.animalName = "";
def getAnimalName(self):
return self.animalName
在本例中,self引用了整个类的animalName变量。记住:如果你在一个方法中有一个变量,self将不起作用。该变量仅在该方法运行时存在。为了定义字段(整个类的变量),您必须在类方法之外定义它们。
如果你一个字都听不懂我在说什么,那么谷歌“面向对象编程”。一旦你明白了这一点,你甚至不需要问那个问题:)。
这个参数的使用,通常称为self并不难理解,为什么它是必要的呢?或者为什么要明确地提到它?我想,对于大多数查找这个问题的用户来说,这是一个更大的问题,如果不是,他们在继续学习python时肯定会有同样的问题。我建议他们阅读以下几篇博客:
1:使用自我解释
注意,它不是关键字。
每个类方法(包括init)的第一个参数始终是对类当前实例的引用。按照惯例,这个参数总是命名为self。在init方法中,self指向新创建的对象;在其他类方法中,它引用被调用方法的实例。例如,下面的代码与上面的代码相同。
2:为什么我们要这样做,为什么我们不能像Java那样把它作为一个参数,而是用一个关键字来代替
我想补充的另一件事是,一个可选的self参数允许我在一个类中声明静态方法,不写self。
代码示例:
class MyClass():
def staticMethod():
print "This is a static method"
def objectMethod(self):
print "This is an object method which needs an instance of a class, and that is what self refers to"
PS:这只适用于Python 3.x。
在以前的版本中,您必须显式地添加@staticmethod装饰器,否则self参数是必须的。
让我们看一个简单的向量类:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
我们需要一个计算长度的方法。如果我们想在类中定义它会是什么样子呢?
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
当我们将它定义为全局方法/函数时,它应该是什么样子?
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
所以整个结构保持不变。我怎样才能利用这个呢?假设我们还没有为Vector类编写length方法,我们可以这样做:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
这是因为length_global的第一个参数可以重用为length_new中的self参数。如果没有显式的自我,这是不可能的。
另一种理解显式self需求的方法是查看Python在哪里添加了一些语法糖。当你记住的时候,基本上,一个电话就像
v_instance.length()
在内部转化为
Vector.length(v_instance)
很容易看出自我在哪里。实际上你不用在Python中编写实例方法;你所写的是类方法,它必须以一个实例作为第一个参数。因此,必须显式地将实例参数放置在某个位置。
The reason you need to use self. is because Python does not use special syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self..