【问题标题】:How to return a value from __init__ in Python?如何在 Python 中从 __init__ 返回一个值?
【发布时间】:2011-01-30 07:31:25
【问题描述】:

我有一个带有__init__ 函数的类。

创建对象时如何从该函数返回整数值?

我写了一个程序,__init__ 进行命令行解析,我需要设置一些值。可以将其设置在全局变量中并在其他成员函数中使用吗?如果是这样怎么做?到目前为止,我在类外声明了一个变量。并将其设置为一个功能不会反映在其他功能中??

【问题讨论】:

  • 如果您正在考虑返回错误代码,请改为引发异常。
  • 请删除您的评论并更新您的问题。你拥有这个问题。这是你的问题。请解决问题以正确显示您的真正问题是什么。你在滥用__init__;如果您描述您真正想要完成的工作,我们可以为您提供帮助。
  • __init__ 可能应该进行命令行解析。定义一个进行实际解析的类方法,并将解析后的值传递给__init__。让__init__ 担心创建必要的属性,而不是弄清楚如何为这些属性生成值。

标签: python class init


【解决方案1】:

__init__ 需要返回 None。你不能(或至少不应该)返回其他东西。

尝试制作任何你想要返回的实例变量(或函数)。

>>> class Foo:
...     def __init__(self):
...         return 42
... 
>>> foo = Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None

【讨论】:

  • +1:您不能返回其他内容。这没有任何意义。
  • init 不返回新创建的对象 - 如 TypeError 中所示,它需要返回 None,对吗?新创建的对象由 new 返回,init 只是设置了它的一些属性。但是,是的,正如您所说,更改 initnew 以返回其他内容确实没有意义。
  • new 在哪里? new 在 Python 中是隐含的吗?我假设 Python 的语义不同于 Java 和其他使用这个词的语言。
  • @Shiva AFAIK,new weronika 的意思是 __new__(self) 不是一般的 java 语义。
  • 不能做不代表没有意义。例如,最好将数据从 super().__init__ 传递到派生类,而不必通过实例变量传递它。
【解决方案2】:

__init__ 不返回任何内容,应始终返回 None

【讨论】:

    【解决方案3】:

    来自documentation of __init__

    作为对构造函数的特殊约束,不能返回任何值;这样做会导致在运行时引发 TypeError。

    作为证明,这段代码:

    class Foo(object):
        def __init__(self):
            return 2
    
    f = Foo()
    

    给出这个错误:

    Traceback (most recent call last):
      File "test_init.py", line 5, in <module>
        f = Foo()
    TypeError: __init__() should return None, not 'int'
    

    【讨论】:

      【解决方案4】:

      你为什么要这样做?

      如果你想在调用类时返回一些其他对象,那么使用__new__() 方法:

      class MyClass(object):
          def __init__(self):
              print "never called in this case"
          def __new__(cls):
              return 42
      
      obj = MyClass()
      print obj
      

      【讨论】:

      • 是的,new 是使用类时返回类实例以外的其他内容的正确方法......我只是想知道 - 你有什么理由可能真的想这样做吗?
      • @weronika 一个想法:在您通常使用工厂的任何情况下,但您有一些理由想要呈现一个看起来像普通类实例化的接口。示例:当在类的__init__ 中添加一些新的可选参数时,您意识到,实际上,为了提供您想要的灵活性,您需要一个返回专门子类实例的类工厂。但是您图书馆的用户已经在使用您现有的 API。要保留它,您需要覆盖 __new__ 以返回您的专用子类的实例。
      • 如果您想查看 Mark Amery 所说的示例,请查看标准库中 datetime 模块的源代码。它以这种方式使用__new__
      • 另外,如果有人想这样做,请确保从对象继承,否则它将无法工作。
      • 我觉得在这一点上,使用常规函数更有意义。对于 Java 维度的人来说可能有点陌生(函数不在类中?异端!)但它是 Pythonic。 (您也可以将属性分配给函数,如 funtionName.val =.. 这有点疯狂,但它有效)
      【解决方案5】:

      __init__ 方法与其他方法和函数一样,在没有 return 语句的情况下默认返回 None,因此您可以将其编写为以下任何一种:

      class Foo:
          def __init__(self):
              self.value=42
      
      class Bar:
          def __init__(self):
              self.value=42
              return None
      

      但是,当然,添加 return None 并不能为您带来任何好处。

      我不确定您的目标是什么,但您可能对以下其中一项感兴趣:

      class Foo:
          def __init__(self):
              self.value=42
          def __str__(self):
              return str(self.value)
      
      f=Foo()
      print f.value
      print f
      

      打印:

      42
      42
      

      【讨论】:

      • 哦..我可以从类中访问成员变量吗?那应该可以解决我的问题....谢谢
      • @lakshmipathi,是的,像这样的实例变量是公开的。
      • 开课后作为oneliner获取有价值的东西返回:f = Foo().value
      • @JLT 是的,你总是这样做,但这并不意味着从__init__ 返回任何东西。
      【解决方案6】:

      问题的示例用法可以是:

      class SampleObject(object):
      
          def __new__(cls, item):
              if cls.IsValid(item):
                  return super(SampleObject, cls).__new__(cls)
              else:
                  return None
      
          def __init__(self, item):
              self.InitData(item) #large amount of data and very complex calculations
      
      ...
      
      ValidObjects = []
      for i in data:
          item = SampleObject(i)
          if item:             # in case the i data is valid for the sample object
              ValidObjects.append(item)
      

      【讨论】:

      • 这将引发 NameError: self is not defined in __new__(cls, Item)
      【解决方案7】:

      只是想补充一下,可以在__init__返回类

      @property
      def failureException(self):
          class MyCustomException(AssertionError):
              def __init__(self_, *args, **kwargs):
                  *** Your code here ***
                  return super().__init__(*args, **kwargs)
      
          MyCustomException.__name__ = AssertionError.__name__
          return MyCustomException
      

      上述方法可帮助您对测试中的异常执行特定操作

      【讨论】:

      • super().__init__ 正在返回 None,所以你正在返回 None,这很好,但是是多余的。
      【解决方案8】:

      好吧,如果你不再关心对象实例......你可以直接替换它!

      class MuaHaHa():
      def __init__(self, ret):
          self=ret
      
      print MuaHaHa('foo')=='foo'
      

      【讨论】:

      • 这只是改变了在构造函数中分配给名称 self 的内容。
      【解决方案9】:

      您可以将其设置为类变量并从主程序中读取:

      class Foo:
          def __init__(self):
              #Do your stuff here
              self.returncode = 42
      bar = Foo()
      baz = bar.returncode
      

      【讨论】:

        【解决方案10】:

        init() return none value 完美解决

        class Solve:
        def __init__(self,w,d):
            self.value=w
            self.unit=d
        def __str__(self):
            return str("my speed is "+str(self.value)+" "+str(self.unit))
        ob=Solve(21,'kmh')
        print (ob)
        

        输出: 我的时速是 21 公里

        【讨论】:

          【解决方案11】:

          解决方案在这里 是的, 尝试从 python 中的 init 方法返回会返回错误,因为它是类的构造函数,您只能为类的范围赋值,但不能返回特定值。 如果你想返回一个值但不想创建一个方法,你可以使用 str 方法

          def __init__(self,a):
              self.value=a
          
             def __str__(self):
              return str("all my return values are possible here")`
          

          【讨论】:

          • __init__initializer,而不是构造函数。 __new__ 是构造函数。
          • __str__ 与从实例化过程中返回值无关。
          【解决方案12】:

          我们不能从 init 返回值。但是我们可以使用 new 来返回值。

          class Car:
              def __new__(cls, speed, unit):
                  return (f"{speed} with unit {unit}")
          
          
          car = Car(42, "km")
          print(car)
          

          【讨论】:

          • 是的,但你不能真正从 __new__ 返回任意值,并且仍然让“协议”类有意义。
          猜你喜欢
          • 2022-01-06
          • 2014-06-28
          • 1970-01-01
          • 2014-04-27
          • 1970-01-01
          • 2014-05-15
          • 2013-06-18
          • 2018-11-23
          • 1970-01-01
          相关资源
          最近更新 更多