向初学者解释“self”变量
向初学者解释“self”变量
我对面向对象编程的术语和概念几乎一无所知。我从概念上知道什么是对象,以及对象有方法。我甚至明白在Python中,类也是对象!这很酷,只是我不知道它意味着什么。我还没有完全理解一些详细的答案,我认为它们会帮助我理解Python:\n
- \n
- Python中的\"yield\"关键字是什么意思?
- Python中的元类是什么?
\n
\n
\n在第一个答案中,作者使用以下代码作为示例:\n
>>> class Bank(): # 让我们创建一个银行,里面有ATM ... crisis = False ... def create_atm(self) : ... while not self.crisis : ... yield "$100"
\n我不立即理解self
指向的是什么。这显然是不理解类的一个症状,我会在某个时候解决这个问题。为了澄清,在\n
>>> def func(): ... for i in range(3): ... print i
\n我理解i
指向range(3)
列表中的一个项,由于它在函数中,所以不是全局的。但是self
指向什么呢?
"self"变量是在调用类实例的方法时自动传递给方法的实例对象,用于标识调用它的实例。在方法内部,可以使用"self"来访问对象的其他属性或方法。(方法基本上就是属于类的函数)
当已经有一个可用的实例时,调用方法时不需要使用"self"。
从方法内部访问"some_attribute"属性:
class MyClass(object): some_attribute = "hello" def some_method(self, some_string): print self.some_attribute + " " + some_string
从现有实例中访问"some_attribute"属性:
>>> # 创建实例 >>> inst = MyClass() >>> >>> # 访问属性 >>> inst.some_attribute "hello" >>> >>> # 调用实例的方法 >>> inst.some_method("world") # 除了"world"外,inst作为第一个参数自动传递给"some_method"。 hello world >>>
下面是一个小示例代码,演示了"self"与实例是相同的:
>>> class MyClass(object): >>> def whoami(self, inst): >>> print self is inst >>> >>> local_instance = MyClass() >>> local_instance.whoami(local_instance) True
正如其他人所提到的,按照约定,它被命名为"self",但它可以被命名为任何其他名称。
对于明确说明local_instance
被传递给方法,并且方法只是在类中定义的函数,给予+1。谢谢!
解释给初学者的“self”变量
在Python中,我们经常看到这样的语法:obj.method(arg1, arg2)
,实际上,这只是一种语法糖,等价于method(obj, arg1, arg2)
(不同的是,method
是通过obj
的类型查找的,而不是全局的)。
如果我们从这个角度来看,obj
实际上是函数的第一个参数,在参数列表中通常被命名为self
(实际上你可以给它取其他名字,代码依然可以正常运行,但其他Python程序员可能会对你皱眉头)。
这种观点还能解释为什么会出现foo() takes exactly n arguments, n+1 given
的错误提示,当调用者传递了n
个参数,但实际上应该传递n-1
个参数。
我认为可以将其理解为type(obj).method(obj, arg1, arg2)
,这样可以避免关于查找的困惑。
所以,这是否意味着每次在类中定义函数时,如果我想让这个函数作用于类的实例上,就需要一个名为self
的必需参数?
是的,而且它必须是第一个参数。(如果你不希望使用类的实例,比如静态方法,为了避免指定(未使用的)self
参数,你必须使用staticmethod
修饰器装饰该方法。)
解决方法:
为了解决初学者对于类和对象的混淆问题,可以通过以下方法进行解释:
首先,需要明确的是,上面的代码块并不是在“创建”一个银行,而是在定义一个银行。一个银行(Bank)是一个具有名为“crisis”的属性和名为“create_atm”的函数的东西。这就是上面的代码所表示的意思。
接下来,我们实际上要创建一个银行:
x = Bank()
现在,x就是一个银行。x具有一个名为“crisis”的属性和一个名为“create_atm”的函数。在python中,调用x.create_atm()与调用Bank.create_atm(x)是一样的,所以现在self指的是x。如果我们再创建另一个名为y的银行,调用y.create_atm()将会查看y的crisis的值,而不是x的,因为在这个函数中,self指的是y。
self只是一个命名约定,但最好坚持使用它。值得指出的是,上面的代码等价于:
class Bank():
crisis = False
def create_atm(thisbank):
while not thisbank.crisis:
yield "$100"
实际上,尽管初学者不需要知道或关心,但在Python中,类也是对象(类型为'type')。
对于上面的评论,我给予了+1,因为它对于类的概念有了很好的解释。我之前没有完全理解类和实例之间的区别,也不知道可以通过Class.method(obj)这种方式来创建对象。
对于这个问题,有人提出了质疑,认为上面的例子是错误的,因为crisis在初始化时没有使用self,因此它是一个类变量,并且在实例之间是共享的。所以,银行x和y检查的是同一个crisis的值?!
我进行了检查。两个例子都是正确的。但我仍然不理解其中的区别。
这似乎是一个经常被问到的问题。你可以在这里找到答案,例如:stackoverflow.com/questions/39039884/…
事实上,x.create_atm()在python中等同于调用Bank.create_atm(x)。我认为这个类比非常有帮助。