想想这个例子:
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,考虑如何在类中调用函数?
以下摘自关于self的Python文档:
As in Modula-3, there are no shorthands [in Python] for referencing the object’s members from its methods: the method function is declared with an explicit first argument representing the object, which is provided implicitly by the call.
Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers, and it is also conceivable that a class browser program might be written that relies upon such a convention.
有关更多信息,请参阅Python类文档教程。
自我是不可避免的。
问题是,self是隐式的还是显式的。
Guido van Rossum解决了这个问题说self必须留下来。
那么自我生活在哪里呢?
如果我们坚持函数式编程,我们就不需要self了。
一旦我们进入Python OOP,我们就会发现自己在那里。
下面是带有方法m1的典型用例类C
class C:
def m1(self, arg):
print(self, ' inside')
pass
ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address
这个程序将输出:
<__main__.C object at 0x000002B9D79C6CC0> outside
<__main__.C object at 0x000002B9D79C6CC0> inside
0x2b9d79c6cc0
self保存类实例的内存地址。
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中编写实例方法;你所写的是类方法,它必须以一个实例作为第一个参数。因此,必须显式地将实例参数放置在某个位置。
当对象实例化时,对象本身被传递到self参数中。
因此,对象的数据被绑定到对象上。下面是一个示例,说明您可能希望如何可视化每个对象的数据。注意“self”是如何被对象名称替换的。我并不是说下面这个示例图是完全准确的,但希望它能在可视化self的使用方面起到一定的作用。
对象被传递到self参数中,这样对象就可以保存自己的数据。
Although this may not be wholly accurate, think of the process of instantiating an object like this: When an object is made it uses the class as a template for its own data and methods. Without passing it's own name into the self parameter, the attributes and methods in the class would remain as a general template and would not be referenced to (belong to) the object. So by passing the object's name into the self parameter it means that if 100 objects are instantiated from the one class, they can all keep track of their own data and methods.
如下图所示: