【问题标题】:Calling constructor of inherited class with only static methods仅使用静态方法调用继承类的构造函数
【发布时间】:2017-11-13 22:57:22
【问题描述】:

我有两个 Python 类。一个继承自另一个。两者都只包含静态方法。继承的类具有需要从外部配置文件初始化的类变量。我试图想出一种方法来调用继承类的构造函数而不创建实例。

下面的代码是我正在做的一个精简示例。该代码有效。但是,我不确定这是否只是不好的做法。我没有理由不在使用前实例化该类。我只是想开发一个不需要实例来完成我需要的解决方案,因为该类只是静态方法。需要调用继承类的构造函数。

另外,谁能告诉我我在方法“foo”中创建的新类实例发生了什么?

import json

class Cloud(object):
    val = None  # ....................................... Class Variable

    def __init__(self):  # .............................. Class Constructor
        with open('config.dat', 'r') as f:
            dat = json.load(f)
        Cloud.val = dat['val']  # ....................... overwrite Class Variable
        print('Class Cloud -- constructor called.')

    @staticmethod
    def foo():  # ....................................... static method, does not require instance
        Cloud.__init__(Cloud.__new__(Cloud))  # ......... call the constructor on a NEW instance
        print('Class Cloud, class variable (val):={}'.format(Cloud.val))

class Sensor(Cloud):

    @staticmethod
    def bar():
        print('bar')

# run Static Method of Inherited Class Cloud
# call Class Cloud constructor
Sensor.foo()

编辑:

Cloud 类用于将数据 MQTT 传输到云服务器。许多其他类都继承自此,因此很容易处理数据传输。 Sensor 类用于从各种传感器收集数据。任何时候都不需要这些类的任何实例,因为数据只是传递。我使用类的原因是将某些方法组合在一起,这同样不是必需的。我唯一需要的是运行 Cloud 的构造函数,以便更新类变量。我可以在静态方法中处理这个问题,但我没有。

再次,只是寻找反馈。好主意,坏主意……

【问题讨论】:

  • 因为您从未在您的__init__ 中真正使用 self,您可以只在__init__ 中使用一次性值,例如NoneCloud.__init__(None, ....)。至于你在foo 中创建的实例会发生什么,它会立即被丢弃,因为你没有保存对它的任何引用。整个方法似乎彻底被误导了。如果你有一堆附加到一个类的方法,其中没有一个使用实例属性,那你到底为什么有一个类呢?
  • IOW 在 Python 中,一个完全由静态方法组成的类可能根本不应该是一个类...
  • 也许您可以在类之外解析 config.dat 的内容,并将它们作为参数提供给类构造函数?每次创建文件实例时让类从文件中读取内容似乎是一种糟糕的模式。
  • @Alex。同意。我只想调用 Cloud 构造函数一次,不管我使用它的方法多少次。
  • 这个类有非静态方法或变量吗?

标签: python inheritance constructor


【解决方案1】:

既然它实际上是一个静态类变量,你就不能在 class 定义中初始化它吗?
我在谈论这样的事情:

import json

class Cloud(object):
    with open('config.dat', 'r') as f:
        dat = json.load(f)
        val = dat['val']
        del dat  # Keep this variable from becoming a class attribute.

    def __init__(self):  # .............................. Class Constructor
#        with open('config.dat', 'r') as f:
#            dat = json.load(f)
#        Cloud.val = dat['val']  # ....................... overwrite Class Variable
        print('Class Cloud -- constructor called.')

    @staticmethod
    def foo():  # ....................................... static method, does not require instance
#        Cloud.__init__(Cloud.__new__(Cloud))  # ......... call the constructor on a NEW instance
        print('Class Cloud, class variable (val): {}'.format(Cloud.val))

class Sensor(Cloud):

    @staticmethod
    def bar():
        print('bar')

# run Static Method of Inherited Class Cloud
# call Class Cloud constructor
Sensor.foo()

这样你就不需要构造一个一次性的Cloud 实例来初始化变量。此外,每次创建实例时都读取(整个)文件似乎效率低下。

【讨论】:

  • 很好的反馈!我其实不知道你能做到这一点。
  • 您可以,因为 Python 中的 class 定义是可执行的,并且在该过程中创建的任何变量都成为类属性——就像其中定义的任何方法一样。如果您不希望变量成为类属性,则需要在(定义的)结束之前将其删除。如果您这样做,要记住的一件事是它在创建类时发生(不是当它的实例存在时,就像它在 __init__() 方法中的情况一样)。
  • 即使我多次调用 Cloud 的方法,它也只会运行一次类定义。我不明白为什么?这是我想要的行为,我只是不知道引擎盖下发生了什么。什么时候创建类?
  • twegner:就是这样设计的。一个类是在其类定义执行时创建的,这通常只在程序执行期间发生一次。我不知道你的情况到底什么时候发生。可能是当它所在的文件作为主脚本显式运行时,或者由于其他一些正在运行的脚本而导致它稍后是imported。
猜你喜欢
  • 2014-06-26
  • 2014-01-31
  • 2018-09-25
  • 2013-02-12
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多