class - python设计的目的是什么?

  显示原文与译文双语对照的内容

self 中的单词的用途是什么? 我理解它引用了从该类创建的特定对象,但我不能明白为什么它需要作为参数添加到每个函数。 为了演示,在 ruby 中我可以这样做:


class myClass
 def myFunc(name)
 @name = name
 end
end

我理解,很容易。 但是在 python 中,我需要包括 self:


class myClass:
 def myFunc(self, name):
 self.name = name

任何人都可以通过这个? 这不是我在( 不可否认有限) 体验中遇到的东西。

时间:

你需要使用 self.的原因是 python 不使用 @ 语法来引用实例属性。 python 决定,以自动执行的方式可以使到的实例方法所属被 传递中的方法,但不能自动接收 : 方法的第一个参数是调用方法的实例。 这使得方法完全与函数相同,并将实际名称留给你使用( 虽然 self 是惯例,但当你使用其他东西时人们通常会对你皱眉。) self 对代码来说不特别,它只是另一个对象。

python --特殊语法,例如 ruby 本可以做一些东西来区分正常的名称来源属性具有或者需要声明像 C++ 和Java做的,也或许有点但是,多个不同 --,但不是。 所有 python 使事情明确,使其明显的是什么,尽管它不做完全无处不在,它为实例属性。 这就是分配给实例属性需要知道要分配给哪个实例的原因,这就是为什么它需要 self.

我也一直很迷惑此时,一段时间,我不认为,出现这种现象的原因有主要与离合器 often-pronounced 显式优于隐式但那里正好适宜以下一个简单的类比。

让我们使用一个简单的向量类:


class Vector(object):
 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)

所以,整个结构保持不变。 现在,我如何利用这个? 如果我们假设一下我们没有书面 length 方法 Vector 类,我们可以这样做:


Vector.length_new = length_global
v = Vector(3, 4)
print v.length_new() # 5.0

这很有效,因为 length_global的第一个参数,可以 re-used length_newself 参数。 如果没有显式 self,这将不可能。


理解显式 self 需要的另一种方法是查看 python 在哪里添加了一些语法糖。 当你记住这一点的时候,你会发现

 
v_instance.length()

 

被内部转换为


Vector.length(v_instance)

可以很容易地看到 self的位置。 实际上,在 python 中并没有编写实例方法;写入的是类方法,( 必须必须) 将实例作为第一个参数。 因此,你必须将实例参数放在显式位置。

假设你有一个类 ClassA,它包含一个定义为:


def methodA(self, arg1, arg2):
 # do something

ObjectA 是该类的一个实例。

现在,当调用 ObjectA.methodA(arg1, arg2) 时,python 会在内部为你转换它:


ClassA.methodA(ObjectA, arg1, arg2)

self 变量引用对象本身。

我喜欢这个例子:


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: []

, 不使用类的代码,我会 demonstrate:


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 )

[migrated my answer from duplicate closed question ]

以下摘录摘自关于自引用的 python 文档:

在Modula-3中,没有 shorthands [in Python] 用于从它的方法引用对象的成员: 方法函数是用显式第一个表示对象的参数声明的,该对象由调用隐式提供。

通常方法的第一个参数命名为self 。 这只不过是一个惯例: 名称本身对 python 没有特殊意义。 但是请注意,没有按照约定代码可能不太读其他 python 程序员,也可以想象,可能编写一个类浏览器的程序,依靠这样一个约定。

有关更多信息,请参阅 python 文档教程关于类。

以及所有其他原因已经表示,它允许容易获得覆盖方法;你可以叫 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 禅宗"explicit比隐式好"。 它实际上是对类对象的引用。 在Java和PHP中,它叫做 this

如果 user_type_name 是你的模型上的一个字段,你可以通过 self.user_type_name 访问它。

self 是对对象本身的对象引用,因此它们是相同的。 python 方法不在对象本身的上下文中调用。 self 中的可以用于处理自定义对象模型或者。

...