【问题标题】:What do __init__ and self do in Python? [duplicate]__init__ 和 self 在 Python 中做什么? [复制]
【发布时间】:2022-12-08 02:21:15
【问题描述】:

我正在学习 Python 编程语言,但遇到了一些我不完全理解的事情。

在这样的方法中:

def method(self, blah):
    def __init__(?):
        ....
    ....

self 是做什么的?这是什么意思?是强制性的吗?

__init__ 方法有什么作用?为什么有必要? (ETC。)

我认为它们可能是 OOP 构造,但我不太了解。

【问题讨论】:

  • 我知道这有超过一百万的浏览量,但从根本上说,它仍然是一个糟糕的问题,应该在一开始就关闭。基本上有两个不相关的问题,这两个问题都用高质量的 QA 对分别解决。当然,这比两者都早,but。更不用说,提供的代码示例是无意义的,那就是编辑猜的在预期的格式。再加上问题的整个文本只是......令人困惑。

标签: python oop self


【解决方案1】:

在这段代码中:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... self 变量表示对象本身的实例。大多数面向对象的语言将 this 作为隐藏参数传递给对象上定义的方法;蟒蛇没有。您必须明确声明它。当您创建 A 类的实例并调用其方法时,它将自动传递,如 ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

__init__ 方法大致代表了 Python 中的构造函数。当您调用A() 时,Python 会为您创建一个对象,并将其作为第一个参数传递给__init__ 方法。任何附加参数(例如,A(24, 'Hello'))也将作为参数传递——在这种情况下会引发异常,因为构造函数不需要它们。

【讨论】:

  • 如果你把x = 'Hello' 放在外面会怎么样在里面但在课堂上?它是否像 java 一样,还是像只初始化一次的静态变量?
  • 它就像一个静态变量。它只初始化一次,可以通过A.xa.x获得。请注意,在特定类上覆盖它不会影响基类,因此 A.x = 'foo'; a.x = 'bar'; print a.x; print A.x 将打印 bar 然后 foo
  • 值得指出的是,第一个参数不一定要称为 self,这只是约定俗成。
  • 类声明中的object 有什么意义?我注意到有些课程有这个,有些则没有
  • @Chris 这是为了与 Python 2 兼容。在 Python 3 中,不需要显式继承自 object,因为它默认发生。
【解决方案2】:

是的,你是对的,这些是 oop 结构。

__init__ 是类的构造函数。 self 参数引用对象的实例(如 C++ 中的 this)。

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

__init__ 方法在为对象分配内存后被调用:

x = Point(1,2)

如果要将值与对象保持一致,请务必在对象的方法中使用 self 参数。例如,如果您像这样实现 __init__ 方法:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

您的 xy 参数将存储在堆栈上的变量中,并在 init 方法超出范围时被丢弃。将这些变量设置为 self._xself._y 会将这些变量设置为 Point 对象的成员(在对象的生命周期内可访问)。

注意在此答案中对“构造函数”一词的使用进行了一些澄清。从技术上讲,“构造函数”的职责在 Python 中分为两种方法。这些方法是__new__(负责分配内存)和__init__(如此处所述,负责初始化新创建的实例)。

【讨论】:

  • 那么有什么理由不希望 self 出现在构造函数中?为什么你甚至必须指定它,如果它是隐式的不是更好吗?
  • 据我所知,__init__不是构造函数,它是创建任何对象时将执行的第一个方法,__init__用于设置对象。 __ new __ 是 python 中的构造函数。
  • 对于阅读此答案的人来说,这是完全错误的。 __init__ 没有在内存中分配空间。期望初始化实例属性。内存中分配的是__new__
  • @black 答案的文字实际上是“The在里面分配对象的内存时调用方法”。它没有说在里面分配内存,它说在分配内存时调用它。也许值得通过将“何时”更改为“之后”来澄清:)
  • @AaronFranke:根据 Python 之禅(在交互式解释器中运行import this),“显式优于隐式”。在这种情况下,允许这样做有一些好处:1) 方法只是在类中定义的函数,需要作为具有隐式 self 传递的绑定方法或具有显式 self 传递的普通函数来调用. 2) 制作classmethods 和staticmethods 意味着您希望能够分别重命名和省略self。 3) 允许在类定义之后将函数附加到类,因此您不能根据上下文更改行为。
【解决方案3】:

一个简短的说明性例子

希望它能有所帮助,这是一个简单的例子,我用来理解在类中声明的变量和在__init__ 函数中声明的变量之间的区别:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345
     
a = MyClass()
print(a.i)
print(MyClass.i)

输出:

345
123

【讨论】:

  • 有趣的观察,但我认为你走错了路。使用 print MyClass.i 它看起来更像是您在调用“静态”变量 i。与 a.i 一样,您调用的是成员变量 i。在我看来,这在里面只是一个构造函数,它在您创建类的对象时首先执行。
  • 这就是我试图通过这个示例“向自己解释”的内容 - __init__ 设置的变量是传递给实例类的,而不是类本身具有相同名称的“静态”变量...
  • 我认为值得注意的是,您创建的第一个 i (i=123) 是一个对象变量,而第二个 i (self.i = 345) 是一个实例变量。虽然类的每个实例的实例变量可以具有不同的值,但类变量在从该类创建的所有实例中都是相同的。 (当然也可以在代码中更改类变量)。所以“静态”变量的正确术语是对象变量,实例变量在类方法中声明(在这种情况下在里面方法,但当然也可以是另一种方法)。
  • 这是什么意思/目的?
  • 它更多地是关于内部运作的,这可能是一个陷阱 - 请参阅我上面的回复评论:-)
【解决方案4】:

简而言之:

  1. self 如其所指,指的是本身- 调用方法的对象。也就是说,如果您有 N 个对象调用该方法,那么 self.a 将为 N 个对象中的每一个引用一个单独的变量实例。假设每个对象都有 N 个变量a
  2. __init__ 是其他 OOP 语言(如 C++/Java)中的构造函数。基本思想是它是一个特别的创建该类的对象时自动调用的方法

【讨论】:

    【解决方案5】:

    类对象支持两种操作:属性引用和实例化

    属性引用使用用于 Python 中所有属性引用的标准语法:obj.name。有效的属性名称是创建类对象时类名称空间中的所有名称。因此,如果类定义如下所示:

    class MyClass:
        """A simple example class"""
        i = 12345
    
        def f(self):
            return 'hello world'
    

    那么MyClass.iMyClass.f是有效的属性引用,分别返回一个整数和一个函数对象。类属性也可以赋值,所以可以通过赋值来改变MyClass.i的值。 __doc__ 也是一个有效属性,返回属于该类的文档字符串:“一个简单的示例类”。

    类实例化使用函数符号。假设类对象是一个返回类的新实例的无参数函数。例如:

    x = MyClass()
    

    实例化操作(“调用”类对象)创建一个空对象。许多类喜欢创建具有针对特定初始状态定制的实例的对象。因此,一个类可以定义一个名为__init__() 的特殊方法,如下所示:

    def __init__(self):
        self.data = []
    

    当一个类定义了一个__init__()方法时,类实例化会自动为新创建的类实例调用__init__()。所以在这个例子中,一个新的、初始化的实例可以通过以下方式获得:

    x = MyClass()
    

    当然,__init__() 方法可能有更大灵活性的参数。在这种情况下,提供给类实例化运算符的参数将传递给__init__()。例如,

    class Complex:
        def __init__(self, realpart, imagpart):
            self.r = realpart
            self.i = imagpart
    
    x = Complex(3.0, -4.5)
    x.r, x.i
    

    取自官方documentation,最终对我帮助最大。


    这是我的例子

    class Bill():
        def __init__(self,apples,figs,dates):
            self.apples = apples
            self.figs = figs
            self.dates = dates
            self.bill = apples + figs + dates
            print ("Buy",self.apples,"apples", self.figs,"figs 
                    and",self.dates,"dates. 
                    Total fruitty bill is",self.bill," pieces of fruit :)")
    

    当您创建 Bill 类的实例时:

    purchase = Bill(5,6,7)
    

    你得到:

    > Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
    > fruit :)
    

    【讨论】:

      【解决方案6】:

      __init__ 确实像构造函数。如果您希望它们表现为非静态方法,则需要将“self”作为第一个参数传递给任何类函数。 “self”是您班级的实例变量。

      【讨论】:

      • 'self' 定义一个方法是否是静态的!哇,这让这个 Java 家伙大开眼界。
      【解决方案7】:

      试试这段代码。希望它能帮助像我一样的许多 C 程序员学习 Py。

      #! /usr/bin/python2
      
      class Person:
      
          '''Doc - Inside Class '''
      
          def __init__(self, name):
              '''Doc - __init__ Constructor'''
              self.n_name = name        
      
          def show(self, n1, n2):
              '''Doc - Inside Show'''
              print self.n_name
              print 'Sum = ', (n1 + n2)
      
          def __del__(self):
              print 'Destructor Deleting object - ', self.n_name
      
      p=Person('Jay')
      p.show(2, 3)
      print p.__doc__
      print p.__init__.__doc__
      print p.show.__doc__
      

      输出:

      Jay

      Sum = 5

      Doc - Inside Class

      Doc - __init__ Constructor

      Doc - Inside Show

      Destructor Deleting object - Jay

      【讨论】:

      • 我不知道是不是只有我一个人,但阅读这段代码有点混乱。也许是因为我还是一个新手 Python 程序员,idk。
      • 我不清楚文件事情..它会提取文档吗?如果我这样做:'''test - my doc''',我可以使用:print.p.__test__吗?还是 doc 是一个特定的关键字?
      • @托马斯文件是文档详细信息的关键字。三重引号用于记录文档,文档是一个可选实体。
      【解决方案8】:

      我自己很难理解这一点。即使在阅读了这里的答案之后。

      要正确理解 __init__ 方法,您需要了解自己。

      自我参数

      __init__ 方法接受的参数是:

      def __init__(self, arg1, arg2):
      

      但我们实际上只传递了两个参数:

      instance = OurClass('arg1', 'arg2')
      

      额外的参数从何而来?

      当我们访问一个对象的属性时,我们是通过名称(或通过引用)来访问的。这里的实例是对我们新对象的引用。我们使用 instance.printargs 访问实例对象的 printargs 方法。

      为了从__init__ 方法中访问对象属性,我们需要引用该对象。

      每当调用方法时,都会将对主对象的引用作为第一个参数传递。按照惯例,您总是将此第一个参数称为您的方法 self。

      这意味着在 __init__ 方法中我们可以这样做:

      self.arg1 = arg1
      self.arg2 = arg2
      

      这里我们在对象上设置属性。您可以通过执行以下操作来验证这一点:

      instance = OurClass('arg1', 'arg2')
      print instance.arg1
      arg1
      

      像这样的值被称为对象属性。这里的 __init__ 方法设置了实例的 arg1 和 arg2 属性。

      来源:http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

      【讨论】:

        【解决方案9】:

        请注意,self 实际上可以是任何有效的 python 标识符。例如,根据 Chris B 的例子,我们可以很容易地写成:

        class A(object):
            def __init__(foo):
                foo.x = 'Hello'
        
            def method_a(bar, foo):
                print bar.x + ' ' + foo
        

        它会完全一样。但是,建议使用 self,因为其他 pythoner 会更容易识别它。

        【讨论】:

        • 我同意推荐使用 self 代替 foo,帮助其他程序员查看代码
        【解决方案10】:

        做什么自己做?它是什么意味着成为?是吗强制的

        每个类方法的第一个参数,包括 init,总是一个引用类的当前实例.按照约定,此参数始终命名为self。在init方法中,self指的是新创建的对象;在其他类方法中,它指的是调用其方法的实例。

        Python不强迫你使用自己“。你可以给它起任何你想要的名字。但是记住方法定义中的第一个参数是对对象的引用. Python 将 self 参数添加到列表中;调用方法时不需要包含它。 如果你没有在 init 方法中提供 self 那么你会得到一个错误

        TypeError: __init___() takes no arguments (1 given)
        

        什么是在里面方法呢?为什么有必要? (ETC。)

        init 是初始化的缩写。它是一个构造函数,当您创建类的实例时会调用该构造函数,并且没有必要.但通常我们的做法是编写 init 方法来设置对象的默认状态。如果您最初不愿意设置对象的任何状态,则不需要编写此方法。

        【讨论】:

          【解决方案11】:
          1. __init__基本上是一个函数“初始化”/“启用”特定对象的类的属性,一旦创建并匹配到相应的类..
          2. self表示将继承这些属性的对象。

          【讨论】:

          • 不必使用“self”关键字,它只是一个占位符。你可以使用任何单词,但建议你使用 self 以帮助提高程序的可读性
          【解决方案12】:

          基本上,在同一类的多个函数中使用变量时,您需要使用“self”关键字。至于在里面,它用于设置默认值,以防没有调用该类中的其他函数。

          【讨论】:

          • Python 中没有“self”关键字。将第一个参数称为“self”只是一种约定。
          • self 基本上用作占位符。不需要你使用 self,你可以使用“eeee”或“foo”或其他东西,只是建议其他程序员在阅读你的代码时使用
          【解决方案13】:

          “自我”是对类实例的引用

          class foo:
              def bar(self):
                      print "hi"
          

          现在我们可以创建一个 foo 的实例并调用它的方法,在这种情况下 self 参数由 Python 添加:

          f = foo()
          f.bar()
          

          但是如果方法调用不在类实例的上下文中,它也可以传入,下面的代码做同样的事情

          f = foo()
          foo.bar(f)
          

          有趣的是,变量名“self”只是一个约定。下面的定义将完全相同..话虽如此非常强的约定应该遵循的总是,但它确实说明了语言的灵活性

          class foo:
              def bar(s):
                      print "hi"
          

          【讨论】:

          • 为什么这说明了语言的灵活性?它只是说你可以给变量任何你选择的合法名称。它与任何其他编程语言有何不同?
          • 正如我在回答中所写,“bar”只是一个函数,其中提供了一个类实例作为第一个参数。因此,虽然“bar”被定义为绑定到“foo”的方法,但它也可以用其他类的实例调用。例如,这不是方法和“this”在 Java 中的工作方式,尽管我想您会看到它们是相同的概念、函数​​和一些实例上下文(实例上下文是 Python 中的第一个参数和 Java 中的“this”) . 也许您现在可以看到我所指的语言的灵活性?
          • 是的,这确实显示了语言的灵活性。从你的回答方式来看,你似乎是在说你可以将“self”变量称为其他东西(比如s)这一事实显示了 python 的灵活性。
          【解决方案14】:

          只是问题的演示。

          class MyClass:
          
              def __init__(self):
                  print('__init__ is the constructor for a class')
          
              def __del__(self):
                  print('__del__ is the destructor for a class')
          
              def __enter__(self):
                  print('__enter__ is for context manager')
                  return self
          
              def __exit__(self, exc_type, exc_value, traceback):
                  print('__exit__ is for context manager')
          
              def greeting(self):
                  print('hello python')
          
          
          if __name__ == '__main__':
              with MyClass() as mycls:
                  mycls.greeting()
          

          $ python3 class.objects_instantiation.py
          __init__ is the constructor for a class
          __enter__ is for context manager
          hello python
          __exit__ is for context manager
          __del__ is the destructor for a class
          

          【讨论】:

            【解决方案15】:

            在这段代码中:

            class Cat:
                def __init__(self, name):
                    self.name = name
                def info(self):
                    print 'I am a cat and I am called', self.name
            

            这里 __init__ 充当类的构造函数,当实例化对象时,将调用此函数。 self 代表实例化对象。

            c = Cat('Kitty')
            c.info()
            

            上述语句的结果如下:

            I am a cat and I am called Kitty
            

            【讨论】:

              【解决方案16】:
              # Source: Class and Instance Variables
              # https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables
              
              class MyClass(object):
                  # class variable
                  my_CLS_var = 10
              
                  # sets "init'ial" state to objects/instances, use self argument
                  def __init__(self):
                      # self usage => instance variable (per object)
                      self.my_OBJ_var = 15
              
                      # also possible, class name is used => init class variable
                      MyClass.my_CLS_var = 20
              
              
              def run_example_func():
                  # PRINTS    10    (class variable)
                  print MyClass.my_CLS_var
              
                  # executes __init__ for obj1 instance
                  # NOTE: __init__ changes class variable above
                  obj1 = MyClass()
              
                  # PRINTS    15    (instance variable)
                  print obj1.my_OBJ_var
              
                  # PRINTS    20    (class variable, changed value)
                  print MyClass.my_CLS_var
              
              
              run_example_func()
              

              【讨论】:

                【解决方案17】:

                在这里,这家伙写得很好很简单:https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

                阅读上面的链接作为对此的参考:

                self?那么所有客户的自我参数是什么 方法?它是什么?为什么,当然是实例!再放一个 方式,像withdraw这样的方法定义了撤回的指令 来自一些抽象客户帐户的钱。呼唤 jeff.withdraw(100.0) 将这些指令用于 jeff 实例。

                所以当我们说 def withdraw(self, amount): 时,我们是在说,“这是如何 您从 Customer 对象(我们称其为 self)取钱,并且 美元数字(我们称之为金额)。 self 是的实例 退出的客户正在被呼叫。那不是我做的 类比,要么。 jeff.withdraw(100.0) 只是简写 Customer.withdraw(jeff, 100.0),这是完全有效的(如果不经常 见)代码。

                在里面self 对其他方法可能有意义,但是在里面?当我们打电话在里面,我们正在创建一个对象,那么怎么可能已经有一个自我呢? Python 允许我们扩展 对象构造时的自我模式,即使 它不完全适合。想象一下 jeff = Customer('Jeff Knupp', 1000.0) 与调用 jeff = Customer(jeff, 'Jeff 克努普', 1000.0);传入的 jeff 也是结果。

                这就是为什么当我们打电话在里面,我们通过说初始化对象 像 self.name = name 这样的东西。请记住,由于 self 是实例, 这相当于说 jeff.name = name,这与 jeff.name = '杰夫克努普。同样,self.balance = balance 也是一样的 作为 jeff.balance = 1000.0.在这两行之后,我们考虑 客户对象“已初始化”并可以使用。

                小心你__init__

                在里面已经完成,调用者可以正确地假设 对象已准备好使用。也就是说,在 jeff = Customer('Jeff Knupp', 1000.0),我们可以开始调用 jeff 的存款和取款; jeff 是一个完全初始化的对象。

                【讨论】:

                  【解决方案18】:

                  Python __init__self 他们是做什么的?

                  self 是做什么的?这是什么意思?是强制性的吗?

                  __init__ 方法有什么作用?为什么有必要? (ETC。)

                  给出的例子不正确,所以让我根据它创建一个正确的例子:

                  class SomeObject(object):
                  
                      def __init__(self, blah):
                          self.blah = blah
                  
                      def method(self):
                          return self.blah 
                  

                  当我们创建对象的实例时,__init__被调用以在创建对象后自定义对象。也就是说,当我们用下面的'blah'调用SomeObject(可以是任何东西)时,它会作为参数传递给__init__函数,blah

                  an_object = SomeObject('blah')
                  

                  self 参数是将分配给an_objectSomeObject 的实例。

                  稍后,我们可能想在此对象上调用一个方法:

                  an_object.method()
                  

                  进行点式查找,即an_object.method,将实例绑定到函数的实例,方法(如上调用)现在是一个“绑定”方法——这意味着我们不需要显式地将实例传递给方法调用。

                  方法调用获取实例,因为它绑定在点式查找上,并且在调用时执行它被编程执行的任何代码。

                  隐式传递的 self 参数按照惯例称为 self。我们可以使用任何其他合法的 Python 名称,但如果将其更改为其他名称,您可能会被其他 Python 程序员指责和指责。

                  __init__是一个特殊的方法,documented in the Python datamodel documentation。它在创建实例后立即被调用(通常通过 __new__ - 尽管 __new__ 不是必需的,除非您正在对不可变数据类型进行子类化)。

                  【讨论】:

                    猜你喜欢
                    • 2010-10-12
                    • 2019-04-21
                    • 2016-11-29
                    • 1970-01-01
                    • 2015-11-04
                    • 1970-01-01
                    相关资源
                    最近更新 更多