Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a class function without triggering the __init__

Is there any way to call functions inside a class without triggering the __init__ part of that class? Let's say I have the next class, usually I'd call the function this way:

class Potato():
    def __init__(self):
        print("Initializing")
    def myfunction(self):
        print("I do something")

Potato().myfunction()

But as expected that prints the Initializing part. Now, If I wanted to call myfunction without triggering that. How would you do it? Pros and cons of doing it? It's even possible?

like image 903
Saelyth Avatar asked Jul 23 '17 18:07

Saelyth


2 Answers

Not sure if this is what you're looking for, but:

A classmethod or a staticmethod could be used without creating an instance of the class - which means that init would not be called that way:

class MyClass:
   def __init__(self):
      print("Initialize instance - not used")

   @staticmethod
   def my_static(toprint):
       print(toprint)

MyClass.my_static("Print this")
like image 148
DonGru Avatar answered Sep 19 '22 06:09

DonGru


Yes, it is possible.

Using a helper function

You could write a helper function that replace __init__ method of your class with a dummy method and then instantiates the class and after this we re-assign the old __init__ back to class.

def skip_init(cls):
    actual_init = cls.__init__
    cls.__init__ = lambda *args, **kwargs: None
    instance = cls()
    cls.__init__ = actual_init
    return instance

Demo:

>>> a = skip_init(Potato)
>>> a.myfunction()
I do something

Overriding __new__

You could override __new__ method of your class and there based on argument you can replace __init__ with a dummy method.

def new_init(cls, init):
    def reset_init(*args, **kwargs):
        cls.__init__ = init
    return reset_init


class Potato():
    def __new__(cls, *args, **kwargs):
        instance = object.__new__(cls)
        lazy = kwargs.pop('_no_init', False)
        if not lazy:
            return instance
        cls.__init__ = new_init(cls, cls.__init__)
        return instance

    def __init__(self):
        print("Initializing")

    def myfunction(self):
        print("I do something")

Demo:

>>> a  = Potato(_no_init=True)
>>> a.myfunction()
I do something
>>> b  = Potato()
Initializing
>>> b.myfunction()
I do something
like image 45
Ashwini Chaudhary Avatar answered Sep 22 '22 06:09

Ashwini Chaudhary