我们都知道下面的代码由于使用了全局变量而不好:
a = 3.14
def inc():
global a
a += 1
inc()
b = a
这太糟糕了,在 python 中,人们必须故意声明 global 来“打破”禁令。但以面向对象的名义,为什么下面的代码是合理的:
class A:
def __init__(self):
self.a = 3.14
def inc(self):
self.a += 1
A_instance = A()
A_instance.inc()
b = A_instance.a
在类实例的范围内,成员变量不就和全局变量一样了吗? “self”基本上将无限制地访问 all 变量给 any 成员函数,无论是否有必要,这使得它非常有状态,容易出错,并且难以阅读(基本上是所有不好的东西)全局变量的特征)?
我们还知道干净且更好的方法是:
def inc(_a):
return _a+1
a = 3.14
b = inc(a)
这样函数 inc() 至少是无状态的并且具有可预测的行为。使用类并使其尽可能无状态的最佳实践是什么?或者根据定义,面向对象是否总是有状态的,并且必须在没有类的情况下进行函数式编程?我还听到人们说 @static 方法很愚蠢,破坏了封装,应该避免......
最佳答案
这取决于您是否需要保存状态。如果您确实需要保存状态,那么需要将其保存在某个地方。类允许您将状态与操作该状态的方法一起保存,并强制执行类本地范围,该范围比在全局范围内存储状态更不易出错。
作为一个具体的例子,我最近实现了一个用于森林模拟的 Tree 类。与树相关的重要变量之一是它的年龄。树龄应该存储在哪里?将其存储在 Tree 类中比存储在其外部更有意义。
如果保护树的年龄不被类外部的代码操纵很重要,我可以使用 Python 优秀的 @property
语法来实现此目的,或者直接通过 Python _varname
变量命名约定。
在类中,是的,树的年龄对其他方法是可见的,但这是一个相对狭窄的范围,如果您的类是根据 SOLID 对象以单一职责编写的,那么肯定不类似于全局范围面向设计原则。
关于oop - 类成员变量不和全局变量一样糟糕吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59571073/