关于oop:向初学者解释python”self”变量

Explaining the python 'self' variable to a beginner

本问题已经有最佳答案,请猛点这里访问。

我对OOP术语和概念相当无知。我从概念上知道对象是什么,并且对象有方法。我甚至理解在Python中,类是对象!很酷,我就是不知道这是什么意思。它不会和我一起点击。

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

  • 在python中,"yield"关键字做什么?
  • 什么是Python中的元类?
  • 在第一个答案中,作者使用以下代码作为示例:

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

    我没有立即摸索埃多克斯1〔0〕所指的。这绝对是一个不理解课程的症状,我将在某个时刻继续学习。澄清,在

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

    据我所知,i指的是清单range(3)中的一个项目,因为它在一个函数中,所以它不是全局的。但是,self指的是什么?


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

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

    那里的评论有点欺骗性。上述代码不"创建"银行。它定义了银行是什么。银行是指具有一个名为crisis的属性和一个函数create_atm的东西。上面的代码就是这么说的。

    现在让我们实际创建一个银行:

    1
    >>> 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只是一个命名约定,但是坚持它是非常好的。值得指出的是,上述代码相当于:

    1
    2
    3
    4
    5
    >>> 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"属性:

    1
    2
    3
    4
    5
    class MyClass(object):
        some_attribute ="hello"

        def some_method(self, some_string):
            print self.some_attribute +"" + some_string

    从现有实例访问"some_attribute"属性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> # 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与实例相同:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> class MyClass(object):
    >>>     def whoami(self, inst):
    >>>         print self is inst
    >>>
    >>> local_instance = MyClass()

    >>> local_instance.whoami(local_instance)
    True

    正如其他人提到的,它按照惯例被命名为"自我",但它可以被命名为任何东西。


    I don't immediately grok what self is pointing to. This is definitely a symptom of not understanding classes, which I will work on at some point.

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

    1
    2
    3
    4
    5
    6
    7
    8
    class Bar(object):
        def someMethod(self):
            return self.field

    bar = Bar()

    bar.someMethod()
    Bar.someMethod(bar)

    最后两行具有相同的行为。(除非barbar的一个子类的对象,否则someMethod()可指另一个功能对象。)

    注意,您可以随意命名"特殊"第一个参数——self只是方法的约定。

    I understand that i points to an item in the list range(3) which, since it is in a function, isn't global. But what does self"point to"?

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

    示例转录:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    >>> 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是指Bank的当前实例。当您创建一个新的Bank并在其上调用create_atm时,python将隐式传递self,并将引用您创建的银行。


    一个鲁比主义者的观点(鲁比是我的第一个编程语言,所以我为我将要使用的任何过于简单化、潜在错误的抽象道歉)

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

    1
    os.path

    这样,os就作为它的第一个变量"无形地"传入path()

    就好像os.path真的是这样:

    1
    path(os)

    如果有菊花链,我可以想象:

    1
    os.path.filename

    在现实中会是这样的*:

    1
    filename(path(os))

    进攻部分来了因此,对于自变量,我们所做的就是允许类方法(从Rubyist的角度来看,python的"instance method s"似乎是类方法…)作为一个实例方法,通过将一个实例作为其第一个变量(通过上面的"鬼鬼祟祟"的点方法)传递给它,该方法按惯例称为self。自我不是一个实例

    1
    2
    c = ClassName()
    c.methodname

    但是阶级本身:

    1
    ClassName.methodname

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

    好的,还需要记住的一点是,有些人把__init__方法称为"魔法"。所以不要担心传递到生成新实例的内容。老实说,可能是nil


    之所以存在"self"(按照约定),是因为当python运行时看到form object.method(param1,param2)的调用时,它使用参数(object,param1,param2)调用方法。所以如果你把第一个参数叫做"自我",每个人都会知道你在说什么。

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

    至于元类,它是很少使用的。你可能想看看:http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html,python最初的作者和当前的仁慈的生活独裁者解释了这是什么,以及它是如何形成的。他也有一篇关于一些可能用途的好文章,但大多数人根本不会直接使用它。


    self是指类的一个实例。