使用Python类而不使用def __init__(self)函数

50

我正在编写一系列文本菜单。使用以下类和子类时,它可以正常运行。但我正在审查我的代码,我在想...我没有在类中使用def __init__(self),这样是否可以?我应该将数据成员放在def __init__(Self):中,例如self.images =(),self.options =()吗?如果我这样做,那么我就不能使用abc模块进行限制,对吗?

class BaseMenu(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def options(self):
        pass

    @abc.abstractproperty
    def menu_name(self):
        pass

    def display(self):
        header = "FooBar YO"
        term = getTerminalSize()
        #sys.stdout.write("\x1b[2J\x1b[H")
        print header.center(term, '*')
        print self.menu_name.center(term, '+')
        print "Please choose which option:"
        for i in self.options:
            print(
                str(self.options.index(i)+1) + ") "
                + i.__name__
            )
        value = int(raw_input("Please Choose: ")) - 1

        self.options[value](self)

class Servers(BaseMenu):

    menu_name = "Servers"
    images = ()
    foo = ()

    def get_images(self):
        if not self.images:
            self.images = list_images.get_images()
        for img in self.images:
            print (
                str(self.images.index(img)+1) + ") "
                + "Name: %s\n    ID: %s" %
                (img.name, img.id)
                )

    def get_foo(self):
        if not self.foo:
            self.foo = list_list.get_list()
        for list in self.foo:
            print "Name:", list.name
            print "  ID:", list.id
            print

    def create_servers(self):
         create_server.create(self)

    options = (
        get_images,
        get_foo,
        create_servers
        )
3个回答

39

你的代码完全没问题。你不必须有一个__init__方法。

即使使用ABC,你仍然可以使用__init__。ABC元类测试的只是名称是否已定义。在__init__中设置images需要定义一个类属性,但你可以先将其设置为None

class Servers(BaseMenu):

    menu_name = "Servers"
    images = None
    foo = None

    def __init__(self):
        self.images = list_images.get_images()
        self.foo = list_list.get_list()

现在您可以对ABC设置约束,要求images抽象属性可用;images = None类属性将满足该约束。


14

你的代码没问题。下面的示例展示了一个最简示例。 你仍然可以实例化一个没有指定 __init__ 方法的类。省略它并不会使你的类成为抽象类。

class A:
    def a(self, a):
        print(a)
ob = A()
ob.a("Hello World")

16
请为你的代码提供上下文。仅包含代码且没有解释或注释的答案并不是很有用。 - pfabri

0
只是为了补充其他答案, 略去 __init__() 也许在我们想要调用类的某些方法时很有用,因为在一些使用情况下重复实例化对象可能会在计算上变得昂贵。
例如,假设你有一个计算器应用程序,Python作为API并将提供计算器结果给客户端。 在 main.py 中考虑以下函数:
import operations

def main():
  ### Some code here ###
  
  result = operations.Operations.calculate_value(value_1)
  # "Operations" is the name of the class in the module.
  # "value_1" is the data being sent from the client.
  
  ### Some code here ###

  return result

为了简单起见,我没有包含处理API调用的样板文件。每当服务器需要处理新请求时,main()函数将被调用。因此,如果访问它的用户数量很高,每次请求到达时创建一个类的实例将是昂贵的。
考虑上面的示例,我们可以在operations.py中定义“操作”,如下所示:
class Operations:
  # Omit __init__() since we will be using only class and static methods.

  # You can use @staticmethod decorator as well here
  # if you don't have any class variables or if you
  # do not need to modify them.
  @classmethod
  def calculate_value(value):
    ### Some code here ###
    
    calculated_value = value + 1
    
    ### Some code here ###

    return calculated_value

这里有一个链接,供想了解staticmethod和classmethod修饰符的人使用:https://realpython.com/instance-class-and-static-methods-demystified/. - chess_madridista
这没有任何意义,在这种情况下,你根本就不应该拥有一个类。仅具有静态方法的类不应该被称为类。虽然有时人们喜欢将类用作简单的命名空间,例如用于配置,但通常如果您不会实例化您的类,那么它可能就不应该是一个类。在这种情况下,它绝对不应该是。 - juanpa.arrivillaga
1
@juanpa.arrivillaga但是,如果应用程序很大,并且我们使用类以更好地维护功能,那么拥有静态方法会有什么害处呢?文档中是否写明,如果定义了类,则始终需要创建该类的实例?如果您能够更清楚地解释您所说的内容,那么也许我就能够理解它,因为我还是个新手 :). - chess_madridista
2
不需要类,只需使用模块。仅包含静态方法的类应该是一个模块。代码库的大小无关紧要。请查看我为此特定问题编写的答案。在这里查看 - juanpa.arrivillaga
1
就性能而言,module.class.method()需要多访问一个属性,因此与module.function()相比会有轻微的性能损失,但实际上性能并不是问题所在。 - juanpa.arrivillaga
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接