57

I am writing a series of text menus. With the class and sub class below it runs with no issues. But I am reviewing my coding and I am wondering....is it ok that I didn't use def __init__(self) in the classes? Should I have placed the data members in def __init__(Self): such as self.images = (), self.options =()? If I did that then I could not use the abc module for restrains, correct?

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 Answers 3

44

Your code is perfectly fine. You don't have to have an __init__ method.

You can still use __init__, even with an ABC. All that the ABC meta tests for is if the names have been defined. Setting images in an __init__ does requires that you define a class attribute, but you can set that to None at first:

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()

Now you can set constraints on the ABC requiring that a images abstract property be available; the images = None class attribute will satisfy that constraint.

Sign up to request clarification or add additional context in comments.

Comments

17

Your code is fine. The example below shows a minimal example. You can still instantiate a class that doesn't specify the __init__ method. Leaving it out does not make your class abstract.

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

2 Comments

Please give context to your code. Answers containing code only without explanation and/or comments are not very useful.
@pfabri idk, was useful to me just seeing a quick example. Concise & to the point refresher
1

Just to add to the other answers, omitting __init__() could be useful when we want to call only certain methods of a class because instantiating an object repeatedly could become expensive computationally in some use cases.

For example, suppose you have a calculator application and Python acts as an API and will provide the results from the calculator to the client. Consider the following function in 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

For simplicity, I have not included the boilerplate for handling API calls. main() will be called every time a new request needs to be processed by the server. So, creating an instance of the class every time when a request arrives will be expensive if the number of users accessing it is high.

Considering the above example, we can define "Operations" in operations.py as shown below:

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

14 Comments

Here is a link for anyone who wants to know about staticmethod and classmethod decorators: realpython.com/instance-class-and-static-methods-demystified.
This doesn't make any sense, in this case, you simply shouldn't have a class at all. A class with only static methods shouldn't be a class. While sometimes people like to use classes as sort of simple namespaces for, for example, configuration, generally if you aren't going to instantiate your class then it probably shouldn't be a class. In this case, it definitely shouldn't be
@juanpa.arrivillaga But if the application is large and if we use classes for better maintainability of the functions, what is the harm in having static methods. Is it written somewhere in the documentation that you always need to create an instance of a class if it is defined? If you could please clarify more on what you are saying, then maybe I might be able to grasp it since I am still a noob :).
No. Instead of a class you would just use a module. A class with only static methods should just be a module. The size of the code base is irrelevant. Here, check out this answer I wrote to a question specifically about this.
Performance-wise, module.class.method() would require one more attribute access, so a minor performance penalty compared to module.function(), but performance isn't the issue really.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.