【问题标题】:Creating a static class with no instances创建一个没有实例的静态类
【发布时间】:2015-08-13 22:19:39
【问题描述】:

我在网上看到的所有教程都展示了如何使用 __init__ 构造函数方法创建类,以便可以声明该类型的对象或该类的实例。

我如何创建一个类(Java 中的静态)以便我可以访问该类的所有方法和属性而不必创建新的实例/对象?

例如:

class World:

    allElems = []

    def addElem(x):  

        allElems.append(x)

World.addElem(6)
print(World.allElems)

编辑

class World(object):

    allAirports = []

    @staticmethod
    def initialize():

        f = open(os.path.expanduser("~/Desktop/1000airports.csv"))
        file_reader = csv.reader(f)

        for col in file_reader:

            allAirports.append(Airport(col[0],col[2],col[3]))

错误:未定义名称“allAirports”

【问题讨论】:

  • 为什么要静态类?你想达到什么目标? - 另见:stackoverflow.com/q/10388127/562769
  • 不要这样做。我不知道Java对你可怜的灵魂做了什么,但这只能以糟糕的方式结束。 allAirports 不仅违反了 PEP 8,而且 - *gasp!* - 一个可变的全局变量。无论你想达到什么目标,你都在尝试以错误的方式实现。
  • 另外,对文件使用with
  • 常规类、静态类和裸函数都有有效的用例。
  • @Jeyekomon 我明白这一点。我认为使用该术语的目的是参考与 Java 的类比。但是,您的措辞表明存在实际区别,我认为澄清值得一提。

标签: python class object static


【解决方案1】:

看来你需要classmethod:

class World(object):

    allAirports = []

    @classmethod
    def initialize(cls):

        if not cls.allAirports:
            f = open(os.path.expanduser("~/Desktop/1000airports.csv"))
            file_reader = csv.reader(f)

            for col in file_reader:
                cls.allAirports.append(Airport(col[0],col[2],col[3]))

        return cls.allAirports

【讨论】:

    【解决方案2】:

    创建静态类的 Pythonic 方法只是在类之外声明这些方法(Java 使用类作为对象和对相关函数进行分组,但 Python 模块足以对不需要任何对象实例的相关函数进行分组)。但是,如果您坚持在类级别创建不需要实例的方法(而不是简单地将其作为模块中的独立函数),则可以使用“@staticmethod”装饰器来实现。

    也就是说,Pythonic 的方式是:

    # My module
    elements = []
    
    def add_element(x):
      elements.append(x)
    

    但是如果你想镜像Java的结构,你可以这样做:

    # My module
    class World(object):
      elements = []
    
      @staticmethod
      def add_element(x):
        World.elements.append(x)
    

    如果您想知道具体的类,您也可以使用@classmethod 执行此操作(如果您希望允许从此类继承的类继承静态方法,这会很方便):

    # My module
    class World(object):
      elements = []
    
      @classmethod
      def add_element(cls, x):
        cls.elements.append(x)
    

    【讨论】:

    • 见上文编辑,我使用了这种方法并收到错误。不知道为什么:/
    • 请注意,Pythonic 方式 仅适用于方法并且会给字段带来问题,因为如果用户通过from module import field 导入字段,他们被导入时的值卡住了。
    • 很好的答案,但 PEP8 是否在其中发挥作用?
    • 深入了解 Java 与 Python 的“类”比较!
    • “创建静态类的 Pythonic 方法就是在类之外声明这些方法” 真的吗?但是,如何利用继承呢?
    【解决方案3】:

    有两种方法可以做到这一点(Python 2.6+):

    静态方法

    class Klass(object):
        @staticmethod
        def static_method():
            print "Hello World"
    
    Klass.static_method()
    

    模块

    你的模块文件,叫做 klass.py

    def static_method():
        print "Hello World"
    

    你的代码:

    import klass
    
    klass.static_method()
    

    【讨论】:

    • 酷!我不知道静态方法!谢谢。
    • 那个模块解决方案很棒。你能在我的编辑中看到上面,为什么我收到以下错误:'allAirports' not defined for static method
    • 你忘了把self放在第12行。应该是self.allAirports.append(Airport(col[0],col[2],col[3]))
    【解决方案4】:

    您可以使用classmethodstaticmethod

    class Paul(object):
        elems = []
    
        @classmethod
        def addelem(cls, e):
            cls.elems.append(e)
    
        @staticmethod
        def addelem2(e):
            Paul.elems.append(e)
    
    Paul.addelem(1)
    Paul.addelem2(2)
    
    print(Paul.elems)
    

    classmethod 的优势在于它可以与子类一起使用,如果你真的想要那个功能的话。

    模块当然是最好的。

    【讨论】:

      【解决方案5】:

      古老的线程,但实现这项工作的一种方法是:

      class Static:
        def __new__(cls):
          raise TypeError('Static classes cannot be instantiated')
      

      然后,你可以这样使用它:

      class Foo(Static): ...
      

      无论如何,对我来说似乎是最“Pythonic”的。

      示例用例:我为类型之间的转换注册处理程序的单例类。

      干杯!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-28
        • 2011-06-07
        相关资源
        最近更新 更多