向初学者解释'self'变量



我对OOP术语和概念相当无知。我从概念上知道对象是什么,知道对象有方法。我甚至明白,在python中,类就是对象!很好,我只是不知道这是什么意思。它不适合我。

我目前正在试图理解一些详细的答案,我认为这些答案将阐明我对python的理解:

  1. 什么是"yield"Python中的关键字do ?
  2. Python中的元类是什么?

在第一个答案中,作者使用以下代码作为示例:

>>> class Bank(): # let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self) :
...        while not self.crisis :
...            yield "$100"

我不能马上明白self指的是什么。这绝对是不理解类的症状,我将在某个时候解决这个问题。为了澄清,在

>>> def func():
...   for i in range(3):
...     print i

我理解i指向列表range(3)中的一个项目,因为它在一个函数中,不是全局的。但是self"指向"什么呢?

我将首先为您澄清一些关于类和对象的混淆。让我们看看这段代码:

>>> class Bank(): # let's create a bank, building ATMs
...    crisis = False
...    def create_atm(self) :
...        while not self.crisis :
...            yield "$100"

这里的注释有点欺骗性。上述代码并没有"创建"一个银行。它定义了什么是银行。银行是一种具有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的危机值,而不是x的,因为在该函数中self指的是y

self只是一个命名约定,但是坚持使用它是非常好的。仍然值得指出的是,上面的代码等价于:

>>> class Bank(): # let's create a bank, building ATMs
...    crisis = False
...    def create_atm(thisbank) :
...        while not thisbank.crisis :
...            yield "$100"

这可能有助于您将obj.method(arg1, arg2)调用语法视为调用method(obj, arg1, arg2)的纯语法糖(除了method是通过obj的类型查找的,并且不是全局的)。

如果你这样看,obj是函数的第一个参数,传统上在参数列表中被命名为self。(事实上,你可以将它命名为其他东西,你的代码将正常工作,但其他Python程序员会对你不满。)

"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"属性:

>>> # create the instance
>>> inst = MyClass()
>>>
>>> # accessing the attribute
>>> inst.some_attribute
"hello"
>>> 
>>> # calling the instance's method
>>> inst.some_method("world") # In addition to "world", inst is *automatically* passed here as the first argument to "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",但它可以被命名为任何名称。

selfBank的当前实例。当你创建一个新的Bank,并在其上调用create_atm时,self将被python隐式传递,并将引用你创建的银行。

我不马上明白self指的是什么。这绝对是不理解类的症状,我会在某个时候解决这个问题。

self是传递给函数的参数。在Python中,第一个参数隐式地是调用该方法的对象。换句话说:

class Bar(object):
    def someMethod(self):
        return self.field
bar = Bar()
bar.someMethod()
Bar.someMethod(bar)

最后两行具有相同的行为。(除非bar指向Bar子类的对象,否则someMethod()可能指向不同的函数对象)

请注意,您可以将"特殊"第一个参数命名为任何您想要的——self只是方法的约定。

我理解i指向列表range(3)中的一个项目,因为它在函数中,不是全局的。但是self"指向"什么呢?

名称self在该函数的上下文中不存在。尝试使用它将引发一个NameError .


示例记录:

>>> class Bar(object):
...     def someMethod(self):
...         return self.field
...
>>> bar = Bar()
>>> bar.field = "foo"
>>> bar.someMethod()
'foo'
>>> Bar.someMethod(bar)
'foo'
>>> def fn(i):
...     return self
...
>>> fn(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
NameError: global name 'self' is not defined

存在"self"的原因(按照惯例)是当Python运行时看到Object.Method(Param1,Param2)形式的调用时,它调用带有参数(Object,Param1,Param2)的Method。如果你把第一个参数叫做self,每个人都会知道你在说什么。

你必须这样做的原因是另一个问题的主题。

作为元类,它很少被使用。你可能想看看:http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html是Python的原作者和现任仁慈独裁者,他解释了这是什么,以及它是如何产生的。他还写了一篇很好的文章,介绍了一些可能的用途,但大多数人根本不会直接使用它。

一个Ruby主义者的观点 (Ruby是我的第一门编程语言,所以我为我将要使用的任何过度简化,可能错误的抽象道歉)

据我所知,点运算符,例如:

os.path

使得os作为path()的第一个变量" invisible "被传递给

如果os.path是真的:

path(os)

如果有雏菊链,我会想象这样:

os.path.filename

在现实中有点像这样*:

filename(path(os))

进攻部分来了因此,对于self变量,所做的就是允许CLASS METHOD(从ruby主义者的角度来看,python的"实例方法"似乎是类方法……)通过将实例传递给它作为其第一个变量(通过上面的"鬼鬼祟祟的"点方法)作为一个实例方法,按照惯例称为self。如果self不是一个实例

c = ClassName()
c.methodname

而是类本身:

ClassName.methodname

类将被传递,而不是实例。

好的,同样重要的是要记住__init__方法被一些人称为"魔法"。所以不要担心传递给生成新实例的是什么。老实说可能是nil

self指的是类的一个实例

最新更新