我可以理解为什么局部变量需要它( self.x ),但为什么nessecary是函数中的参数?还有什么东西可以放在那里而不是自己吗?
请尽可能多地解释外行人的条款,我从未接受过体面的编程教育。
答案 0 :(得分:3)
默认情况下,在类的命名空间中声明的每个函数都假定它的第一个参数是对该类实例的引用。 (其他类型的函数用@classmethod
和@staticmethod
修饰以改变这种假设。)这些函数称为方法。按照惯例,Python程序员将第一个参数命名为self
,但Python并不关心你所谓的它。调用方法时,必须提供该引用。例如(将self
替换为foobar
以证明self
不是必需的名称):
class A:
def __init__(foobar):
foobar.x = 5
def somefunc(foobar, y):
print foobar.x + y
a = A()
print A.somefunc(a, 3) # Prints 8
Python提供了一些语法糖,通过让你调用绑定方法而不是函数本身来使对象和调用它的方法之间的链接变得更加明显。也就是说,a.somefunc(3)
和A.somefunc(a, 3)
是等价的。在Python术语中,A.somefunc
是一种未绑定的方法,因为它在调用时仍需要一个实例:
f = A.somefunc
print f(a, 3)
相比之下,a.somefunc
被称为绑定方法,因为您已经提供了要用作第一个参数的实例:
f = a.somefunc
print f(3)
答案 1 :(得分:2)
如果你考虑它,每种编程语言都会这样做 - 或者至少是像pascal,c ++或java那样最常用的语言。除此之外,在大多数编程语言中,假定this
关键字并且不作为参数传递。考虑这些语言中的函数指针:它们与方法指针不同。
帕斯卡:
function(a: Integer): Integer;
VS
function(a: Integer): Integer of object;
后者考虑self
指针(是的,它命名为self
,但它是一个隐式指针,如c ++中的this
,而python { {1}}是明确的。)
C ++:
self
VS
typedef int (*mytype)(int a);
与Pascal不同,在C ++中,您必须指定拥有该方法的类。无论如何,这个方法指针声明表明期望typedef int Anyclass::(*mytype)(int a);
的函数之间的差异。
但是Python非常重视Zen,因为quichua人认真对待他们的Ama Suway,Ama Llullay,Ama K' ellay:
this
那么,这就是为什么你看到显式 Explicit is better than implicit.
参数(当然必须为它编写)和实例方法self
的原因(尽管如此& #39; s通常称为@classmethod
,因为它的目的是动态地知道类而不是实例。 Python不假设方法中必须存在cls
或this
关键字(因此,命名空间只有真正的变量 - 请记住,您不必将它们命名为self
或{{1}虽然它是通常的和预期的)。
最后,如果你得到:
self
您必须将其称为
cls
获得它时:
x = AClass.amethod #unbound method
必须将称为:
x(aninstance, param, param2, ..., named=param, named2=param2, ...)
是的,x = anInstance.method #bound method, has `im_self` attribute set to the instance.
在参数列表中是明确的,因为它没有被假定为关键字或后门'必须存在,但不是在参数列表中,因为每个OOP语言都有语法糖(怪异的标准,呵呵?)。
答案 2 :(得分:1)
Python的面向对象编程的实现如何工作 - 一个实例的方法(一个所谓的绑定方法)被调用,该实例作为它的第一个参数。
除了实例的变量(self.x
)之外,您还可以将其用于其他任何事情,例如调用另一个方法(self.another_method()
),将此实例作为参数传递给其他完全(mod.some_function(3, self)
),或者使用它在此类的超类中调用此方法(return super(ThisClass, self).this_method()
)。
你可以给它一个完全不同的名字。使用pony
代替self
也可以。但是你不应该出于显而易见的原因。
答案 3 :(得分:1)
在方法中使用self
作为第一个引用完全是惯例。
您可以将其称为其他内容,即使在同一个类中也不一致:
class Foo(object):
def __init__(notself, i):
notself.i=i # note 'notself' instead of 'self'
def __str__(self):
return str(self.i) # back to the convention
f=Foo(22)
print f
但请不要这样做。对于可能会读取您的代码的其他人(或者您稍后阅读时自己)会感到困惑。