Python 是否允许在init方法中使用方法?

Python 是否允许在init方法中使用方法?,python,python-3.x,object,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 现在我在想,是否有可能在创建对象时获得周长的

我刚开始在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)
这是你能做到的吗? 如果是,这是一种好的做法吗


如果没有,那么仅使用边获取周长的最佳方法是什么?

您应该在同一类中与self一起引用该方法


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


_uuuinit_uuu方法没有什么特别之处,只是在对象构造过程中会自动调用它uuu new_uuu创建对象,然后uuu init_uuu对其进行初始化。因此,你可以在它里面做任何你需要做的事情。但是,您需要确保不会无意中执行会导致对部分初始化的对象执行操作的操作。使用下面的@property可以解决大多数边缘情况

这里唯一的区别是,在大多数情况下,调用self.method比调用methodself更好

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 decorator将peripherm方法转换为可以访问的属性,就像它是另一个属性一样,但是它是在请求时计算出来的。

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

这里唯一的区别是,在大多数情况下,调用self.method比调用methodself更好

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 decorator将perimum方法转换为可以访问的属性,就像它是另一个属性一样,但它是在请求时计算的。

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

假设你有以下课程:

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)
,因为Thing.\uuuu init\uuuu调用SubThing.compute\u size,SubThing.compute\u size假设self.more\u东西已经准备好了,但还没有准备好:

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'

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

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

假设你有以下课程:

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)
,因为Thing.\uuuu init\uuuu调用SubThing.compute\u size,SubThing.compute\u size假设self.more\u东西已经准备好了,但还没有准备好:

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'

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

这是一个很好的做法。您应该在一个地方实现一个算法,比如周长计算,这样它只需要验证一次,如果需要更改代码,您就不必搜索代码。另外,当你创建子类时,你可以利用它来考虑一个等边三角形,这个三角形可以与一个GETZ周界的变化一起分享…但你可能还没走那么远。这是一个很好的做法。您应该在一个地方实现一个算法,比如周长计算,这样它只需要验证一次,如果需要更改代码,您就不必搜索代码。另外,当你创建子类时,你可以利用它来考虑一个等边三角形,这个三角形可以与一个GETZ周界的变化一起分享…但你可能还没有做到这一点。它不是作为_; new _;的一部分调用的;负责调用_unew _uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!实际上,我把这个想法作为遗传算法的家庭作业,所以我需要从一开始就构建它。根据@user2357112注释进行编辑。它不是作为_new_;的一部分调用的;负责调用_unew _uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!实际上,我把这个想法作为遗传算法的一个家庭作业,所以我需要从一开始就构建它。根据@user2357112评论编辑。非常感谢,稍后我会在我们的
ee子类可能最好完全避免继承;。但更严肃地说,我欣赏这种观点。当我使用初始化属性的方法时,我总是感到很痛苦。这就证明了我的犹豫是有道理的。非常感谢,我稍后会回来看这篇文章,我们看到子类可能是完全避免继承的最好方法;。但更严肃地说,我欣赏这种观点。当我使用初始化属性的方法时,我总是感到很痛苦。这证明我的犹豫是有道理的。