【问题标题】:Doubts regarding __init__ in pythonpython中关于__init__的疑问
【发布时间】:2018-06-02 23:28:00
【问题描述】:

我最近正在通过某些在线课程学习 Python 课程,所以我完全是 Python 新手。

版本 [1]

class Bubble:

    def __init__(self, pos, vel, colour):
        self.pos = list(FIRING_POSITION)
        self.vel = [0, 0]
        self.color = random.choice(COLOR_LIST)

版本 [2]

class Bubble:

    def __init__(self):
        self.pos = list(FIRING_POSITION)
        self.vel = [0, 0]
        self.color = random.choice(COLOR_LIST)

我的疑问是:

(1) 比较Version [1]Version [2],不知道什么时候需要放pos等变量>velcolour 转换为 __init__(self) 作为 __init__(self, pos, vel, colour)

(2) 这两个版本有什么区别?

【问题讨论】:

  • 在 (1) 中,您没有使用您传入的任何参数,因此它们毫无意义 - 您不需要传入参数,除非您需要将它们用于某些事情(它是与任何其他功能没有什么不同)。否则,它们都会“工作”。
  • 感谢您的快速回复!

标签: python initialization arguments init


【解决方案1】:

对于初学者来说,第一个例子没有多大意义。 __init__ 接受参数但不对它们做任何事情,并且实例属性的值仍然是硬编码的。

一个更明智的例子是:

class Bubble:
    def __init__(self, pos, vel, color):
        self.pos = pos
        self.vel = vel
        self.color = color

现在将它与您提供的第二个示例进行比较是有意义的。

在上面的示例中,Bubble 将接受 3 个参数并将它们分配给实例属性。没有任何东西是硬编码的,调用代码可以控制所创建实例的属性(Bubble(position_1, [1, 2], blue)Bubble(position_2, [3, 3], yellow) 等)。

在您提供的第二个示例中,调用代码对用于初始化实例属性的值的控制为零,因为它们在__init__ 的代码中硬编码,并且创建Bubble 对象的方法将是Bubble().

一种常见的方法是通过使用具有默认值的参数来适应这两种用例(请注意不要使用可变的默认参数):

class Bubble:
    def __init__(self, pos=None, vel=None, color=None):
        if pos is None:
            self.pos = list(FIRING_POSITION)
        else:
            self.pos = pos
        if vel is None:
            self.vel = [0, 0]
        else:
            self.vel = vel
        if color is None:
            self.color = random.choice(COLOR_LIST)
        else:
            self.color = color

这可以写得更简洁

class Bubble:
    def __init__(self, pos=None, vel=None, color=None):
        self.pos = pos or list(FIRING_POSITION)
        self.vel = vel or [0, 0]
        self.color = color or random.choice(COLOR_LIST)

这种方式提供了精细控制,并且可以使用任何参数组合(0、1 或 2 和 3 个参数的任意组合)调用 Bubble

【讨论】:

  • 非常感谢您提供如此详细的信息!这对我很有用!
【解决方案2】:

对您的Version[1] 代码稍作修改,会更清晰。

版本[1]

class Bubble:
    def __init__(self, pos, vel, colour):
        self.pos = pos
        self.vel = vel
        self.color = color

正如您现在所知道的,我们正在将参数传递给init function,它被用于分配类中每个成员的值。

这样你的对象就创建好了,比如:

bubbleObj = Bubble(1, [0,0], "red")

#驱动值:

>>> bubbleObj.pos
=>  1

然而,在您的 Version[2] 代码中,不可能进行此类参数化。所以在这种情况下,对象的创建方式如下:

bubbleObj = Bubble()

这分别类似于 parameterised constructordefault constructor 的 C++ 约定。

如需进一步阅读,请查看Pydoc for Classes

【讨论】:

    【解决方案3】:

    版本 1

    当你用

    初始化这个类时
    Bubble1 = Bubble(pos, vel, colour) # args are required here
    

    初始化会成功,但不会使用您作为参数输入的 pos、vel 和 color 的值,因为您正在创建类变量 self.pos, self.vel, self.color 而不使用从参数接收到的值。

    如果你像这样进行类变量初始化:

    def __init__(self, pos, vel, colour):
        self.pos = pos
        self.vel = vel
        self.colour = colour
    

    那么这将是 init 函数的更正确用法。您在版本 1 中所做的不是使用您在创建类对象时传递的参数。

    版本 2

    似乎是正确的。您正在 init 方法中分配类变量 self.pos, self.vel, self.color。假设您可以正确访问list(FIRING_POSITION) 的值,则此函数将起作用。而且由于您不需要将任何参数分配给类 var,因此可以使用以下方式实例化该类:

    Bubble2 = Bubble() #  no args in here
    

    【讨论】:

      【解决方案4】:

      如果您了解为特定问题设计类的基本思想,OOP 的实现看起来会更有用。举个例子吧:

      class Person:
      
          def __init__(self, name, surname, birthdate,email):
              self.name = name
              self.surname = surname
              self.birthdate = birthdate
              self.email = email
      

      这里的Person 是一个蓝图,表示您将要创建的实例。而且,namesurnamebirthdateemail 的所有属性都特定于特定实例,基于这些属性,我们可以定义任何人的状态。而且,您可能需要计算 Person 的多个实例并根据您的要求计算其他属性。

      在你的情况下,

      class Bubble:
      
          def __init__(self, pos, vel, colour):
              pass
      

      尽管您传递了pos, vel, colour,但您并没有根据这些参数定义属性。这意味着,那些传递的值并不代表真实场景中的Bubble

      如果您认为pos, vel, colour 是定义statestate 的属性/属性,那么您应该将您的类定义为:

      class Bubble:
      
          def __init__(self, pos, vel, colour):
              self.pos = pos
              self.vel = vel
              self.colour = colour
      

      【讨论】:

        猜你喜欢
        • 2020-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 2012-04-02
        • 2013-08-08
        • 1970-01-01
        相关资源
        最近更新 更多