什么时候应该在Python中使用类和self方法?

时间:2019-05-11 09:26:05

标签: python oop

我一直在尝试编写一个Python程序,根据距4个锚点的距离来计算点的位置。我决定将其计算为4个圆的交点。

我有一个问题,不是关于算法,而是关于此类程序中类的使用。我对OOP确实没有太多经验。真的需要在这里使用类吗?还是至少以某种方式改进了程序?

这是我的代码:

while (condition) {
  DoSomething(); //contains a loop too
  Debug.Log (value);
  Application.Quit ();
}

此外,我不太了解应该在何处使用self关键字以及在哪些地方不必要。

2 个答案:

答案 0 :(得分:4)

类和OOP始终是恕我直言的一个不错的选择,通过使用它们,您将能够更好地组织和重用代码,可以创建从现有类派生的新类以扩展其功能(继承性)或进行更改如果需要它(多态性)以及封装代码内部,则它的行为将变得更安全(不过,在Python中没有真正的封装)。

例如,在您的特定情况下,您正在构建一个使用一种技术来计算交集的计算器,如果其他使用您的班级的人想要修改该行为,则他们可以覆盖该函数(这实际上是多态):

class PointCalculator:
    def intersection(self, P1, P2, dist1, dist2): 
        # Your initial implementation

class FasterPointCalculator(PointCalculator):
    def __init__(self):
        super().__init__()

    def intersection(self, P1, P2, dist1, dist2):
        # New implementation

或者,您将来可以扩展该类:

class BetterPointCalculator(PointCalculator):
        def __init__(self):
            super().__init__()

        def distance(self, P1, P2):
            # New function

您可能需要使用一些必需的数据来初始化您的类,并且您可能不希望用户能够对其进行修改,您可以通过用下划线命名变量来表示封装:

class PointCalculator:
    def __init__(self, p1, p2):
        self._p1 = p1
        self._p2 = p2

    def do_something(self): 
        # Do something with your data
        self._p1 + self._p2

您可能已经注意到,调用函数时会自动传递self,它包含对当前对象(类的实例)的引用,因此您可以访问其中声明的任何内容,例如示例中的_p1和_p2以上。

您还可以创建类方法(静态方法),然后您将无法访问self,您应该对执行常规计算的方法或不需要特定实例的任何操作执行此操作,您的交集方法可以成为好候选人,例如

class PointCalculator:

    @staticmethod
    def intersection(P1, P2, dist1, dist2): 
        # Return the result

现在,您不需要PointCalculator的实例,只需调用PointCalculator.intersection(1, 2, 3, 4)

使用类的另一个优势可能是内存优化,Python将在对象超出范围时将其从内存中删除,因此,如果您的长脚本中包含大量数据,则在脚本终止之前它们不会从内存中释放

话虽如此,对于执行非常特定任务的小型实用程序脚本,例如,安装应用程序,配置某些服务,运行某些OS管理任务等...一个简单的脚本完全可以,并且是其中之一。 Python如此受欢迎的原因。

答案 1 :(得分:2)

不,您编写代码类的方式是不必要的,并且会使代码明显变差。

让我们看看如何用procedural styleobject oriented风格进行一些几何设计。

过程编程就是编写函数(过程),这些函数需要一些数据,对其进行处理并返回一些数据。

def area_circle(radius):
    return math.pi * radius * radius

print(area_circle(5))

您有一个圆的半径,便得到了面积。

面向对象的编程是关于要求数据做事。

class Circle():
    def __init__(self, radius=0):
        self.radius = radius

    def area(self):
        return math.pi * self.radius * self.radius

circle = Circle(radius=5)
print(circle.area())

您有一个圆圈,并询问其面积。

对于非常微妙的区别,这似乎有很多额外的代码。

现在,如果您需要计算其他形状怎么办?这是OO中的Square。

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

    def area(self):
        return self.side * self.side

square = Square(side=5)
print(square.area())

现在是程序性的

def area_square(side):
    return side * side
print(area_square(5));

那又怎样?当您要计算形状的面积时会发生什么?在程序上,您必须传递各种类型的形状的数据,并告诉您的区域函数它是哪种形状,并且区域函数必须知道如何解释不同形状的形状数据。

def area(type, shape_data):
    if type == 'circle':
        return area_circle(shape_data)
    elif type == 'square':
        return area_square(shape_data)

print(area('circle', 5))
print(area('square', 5))

在OO中就是这个。

print(shape.area())

无论shapeCircle还是Squareshape.area()都可以使用。使用形状的人您不需要了解其工作原理。

随着添加更多形状,程序代码在需要使用形状的任何地方都变得越来越复杂。 OO代码保持完全相同,相反,您编写了更多类。

这就是OO的重点:将如何完成工作的细节隐藏在接口后面。只要结果相同,对您的代码来说它如何工作都无关紧要。