【问题标题】:python should class variables be initialised to a dummy value when real value is yet to be assigned?当尚未分配实际值时,python应该将类变量初始化为虚拟值吗?
【发布时间】:2020-09-26 00:45:10
【问题描述】:

我在 python 中有一个主要是静态方法的类。这些静态方法为类变量分配一些值,如下所示:

class A:

    @staticmethod
    def foo():
        A.first = 20

    @staticmethod
    def foo2():
        return A.first **2

在我的情况下,foo2 将始终在 foo 之后运行。我的问题是我应该将first 初始化为类范围内的某个虚拟值,例如:

class A:
    A.first = None

    @staticmethod
    def foo():
        A.first = 20

    @staticmethod
    def foo2():
        return A.first **2

注意:当在foo2 中访问first 时,IDE 会发出unresolved attribute reference 'first' for class A 的警告。这个警告是合理的,这就是为什么我想将first 初始化为一个虚拟占位符。

这里的最佳做法是什么?

【问题讨论】:

  • “我在 python 中有一个主要是静态方法的类。这些静态方法为类变量分配一些值,如下所示:”这没有任何意义。为什么不使用实例变量?此外,如果您要修改类状态,您可能应该使用classmethods 而不是 staticmethods。但从根本上说,“python 中的一个主要是静态方法的类”是主要的代码气味。
  • 我同意先初始化它(就像你的第二个代码一样)。您可能不应该相信foo2 会调用foo 并插入assert A.first is not None。 Disclamer:我还假设您展示的是一个相当简化的示例,因为正如上面的评论所述,这个示例本身就是糟糕的设计。
  • 那么静态方法的意义何在?我知道我不会有这个类的多个实例。那么为什么不制作静态方法呢? (其实其他编程语言也有静态类之类的东西)
  • 关于 @static@class 方法和 代码气味 与否:如果你有一个只有 @staticmethods @classmethods 和类变量的类,那么这是创建名称空间的一种方式。您可以使用单独的模块实现相同的目的。我真的不能说,这是不好的做法还是好的做法。以及使用单独的模块是否更好。我认为这是一种可能的编码方式,尽管我主要使用模块
  • @user7331538 静态方法的存在主要是为了安抚来自像 Java 这样的语言的人,其中一切都是类定义。 Python 中代码组织的基本单位是模块,而不是类。如果您打算用另一种语言创建一个静态类,那么在 Python 中,应该只是一个包含常规函数的模块。如果您在该模块中有可变的全局状态,那么您应该使用实例来开头。

标签: python class oop class-variables


【解决方案1】:

我个人认为编写代码非常好,它被 flakeflake8prospectorpylint 或任何您的 IDE 使用的工具标记为干净。

在某些情况下,这意味着编写并非绝对必要的行或以稍微不同的方式重写代码只是为了取悦一个工具。 我认为这主要是值得的。

在大多数情况下,它有助于避免难以阅读的代码或奇怪的错误。 这意味着,即使不是绝对必要,最好显式声明具有虚拟值的类变量,即使稍后会设置实际值。

阅读你的代码的人会更容易看到,你有类变量。

另一条评论:

虽然

class A:
    ...

    @staticmethod
    def foo():
        A.first = 20

有效,有点奇怪。

@staticmethod 适用于既不需要任何类属性也不需要类实例的函数,但是您可以 显式 引用A

比较常见的是写法:

class A:
    ...

    @classmethod
    def foo(cls):
        cls.first = 20

@classmethod 表示,您想要访问类成员或其他类方法,但不需要实例。这正是您想要实现的目标。

这还有一个优点,如果您创建一个继承自 A 的类,那么问题就会更少(如果您曾经重命名该类,那么需要更改的行就更少了)

【讨论】:

  • 是的,你是对的。但是我不想重复已经讨论过的代码。如您所见,我也没有添加foo2 的声明。我将做一个微小的更改(添加...)以明确这只是部分代码。如果您认为这不清楚,我可以按照您的建议添加 first = None 告诉我您的想法 或者我可以删除标题行 class A:
  • 我想改进我的答案,使其易于阅读、完整且不含糊。答案被否决了。很高兴告诉我可以改进的地方。我非常有动力改进我的答案,以便它们对 SO 有用。只是反对投票并没有太大帮助。我收到一个反馈(同时被删除)建议将first = None 添加到我的两个示例中。我回答并询问我建议的修复是否可行,或者添加first = None 是否会更好。从来没有得到答案,只是看到赞成票变成了反对票。
猜你喜欢
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 2012-03-25
  • 2015-07-04
相关资源
最近更新 更多