想想这个例子:

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相同)。

其他回答

我将用不使用类的代码演示:

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

类只是一种避免始终传递这种“状态”的方法(以及其他一些不错的事情,如初始化、类组合、很少需要的元类,以及支持自定义方法来覆盖操作符)。

现在让我们使用内置的python类机制来演示上面的代码,以展示它们基本上是相同的东西。

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[把我的答案从重复的封闭式问题中迁移过来]

与前面提到的所有其他原因一样,它允许更容易地访问被覆盖的方法;你可以调用Class.some_method(inst)。

举个例子说明它的用处:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"

我想说,至少对于Python, self参数可以被认为是一个占位符。 看看这个:

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

p1 = Person("John", 36)

print(p1.name)
print(p1.age)

Self在这里,还有很多其他的被用作存储name值的方法。然而,在此之后,我们使用p1将其分配给我们正在使用的类。然后当我们打印它时,我们使用相同的p1关键字。

希望这对Python有所帮助!

我喜欢这个例子:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []

自我是不可避免的。

问题是,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的目的是保存实例方法的引用,并使我们能够显式地访问该引用。


注意有三种不同类型的类方法:

静态方法(读作:函数), 类方法, 实例方法(已提到)。