想想这个例子:
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 )
[把我的答案从重复的封闭式问题中迁移过来]
我想说,至少对于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有所帮助!
自我是不可避免的。
问题是,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的目的是保存实例方法的引用,并使我们能够显式地访问该引用。
注意有三种不同类型的类方法:
静态方法(读作:函数),
类方法,
实例方法(已提到)。