你是否可以在init方法中使用方法?

时间:2018-03-24 04:57:03

标签: python python-3.x object

我刚刚开始在python3中学习OOP,今天我们就开始了这个小课程。

class Square:

    def __init__(self, side):
        self.side = side

    def show_perimeter(self):
        print(self.side * 4)

test_square = Square(10)
test_square.show_perimeter()
>> 40

现在我正在考虑是否可以在创建对象时获取周长的值,例如......

class Square:

    def __init__(self, side):
        self.side = side
        self.permiter = get_perimeter(self)

    def get_perimeter(self):
        return self.side * 4

test_square = Square(10)
print(test_square.perimeter)

这是你能做的吗? 如果是这样,这是一个好习惯吗?

如果没有,那么通过使用侧面来获得周边的最佳方法是什么?

3 个答案:

答案 0 :(得分:6)

__init__方法没有什么特别之处,除了它作为构造对象的一部分自动调用(__new__创建对象,__init__初始化它)。因此,您可以在其中做任何您需要做的事情。但是,您需要确保不会无意中执行会对部分初始化对象执行操作的操作。使用下面的@property可以解决大部分边缘情况。

唯一的区别是,在大多数情况下调用self.method()而不是method(self)是更好的形式。

class Square:

    def __init__(self, side):
        self.side = side
        self.permiter = self.get_perimeter()

    def get_perimeter(self):
        return self.side * 4

test_square = Square(10)
print(test_square.perimeter)

但是,我想指出在这种情况下财产可能更好:

class Square():
  def __init__(self, side):
    self.side = side;

  @property
  def perimeter(self):
    return self.side * 4

x = Square(10)
print(x.perimeter)
>>> 40

在这种情况下,@property装饰器将perimeter方法转换为可以被访问的属性,就像它是另一个属性一样,但它是在被要求时计算的。

答案 1 :(得分:3)

这是允许的,但它也比人们通常意识到的要危险得多。

说你有以下课程:

class Thing:
    def __init__(self):
        self._cached_size = self.compute_size()
    def compute_size(self):
        return 1000

这似乎可以自行运行,但是如果你尝试将其子类化:

class SubThing(Thing):
    def __init__(self, more_stuff):
        super().__init__()
        self.more_stuff = more_stuff
    def compute_size(self):
        return super().compute_size() + self.more_stuff

SubThing(5)

Everything goes to pieces,因为Thing.__init__调用SubThing.compute_sizeSubThing.compute_size假设self.more_stuff已准备就绪,但尚未就绪:

Traceback (most recent call last):
  File "./prog.py", line 14, in <module>
  File "./prog.py", line 9, in __init__
  File "./prog.py", line 3, in __init__
  File "./prog.py", line 12, in compute_size
AttributeError: 'SubThing' object has no attribute 'more_stuff'

你基本上不应该调用__init__中你希望被覆盖的方法,因为你的对象处于一个非常不稳定的半构造状态,特别是子类负责的状态部分。

如果你想使用你自己的类的方法版本并忽略覆盖(避免子类状态的问题),你可以直接调用它:

class Thing:
    def __init__(self):
        self._cached_size = Thing.compute_size(self)
    def compute_size(self):
        return 1000

有些人可能会建议在调用super().__init__之前让子类初始化它们的状态,但这会导致一个非常混乱的不同类的混乱,这取决于其他类的特定部分是否准备就绪。这不会减少你遇到的问题。

答案 2 :(得分:1)

您应该使用self在同一个类中引用该方法。

class Square:

    def __init__(self, side):
        self.side = side
        self.perimeter = self.get_perimeter()

    def get_perimeter(self):
        return self.side * 4