Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to instantiate a class without calling __init__?

Is there a way to circumvent the constructor __init__ of a class in python?

Example:

class A(object):         def __init__(self):         print "FAILURE"      def Print(self):         print "YEHAA" 

Now I would like to create an instance of A. It could look like this, however this syntax is not correct.

a = A a.Print() 

EDIT:

An even more complex example:

Suppose I have an object C, which purpose it is to store one single parameter and do some computations with it. The parameter, however, is not passed as such but it is embedded in a huge parameter file. It could look something like this:

class C(object):     def __init__(self, ParameterFile):         self._Parameter = self._ExtractParamterFile(ParameterFile)     def _ExtractParamterFile(self, ParameterFile):         #does some complex magic to extract the right parameter         return the_extracted_parameter 

Now I would like to dump and load an instance of that object C. However, when I load this object, I only have the single variable self._Parameter and I cannot call the constructor, because it is expecting the parameter file.

    @staticmethod     def Load(file):         f = open(file, "rb")         oldObject = pickle.load(f)         f.close()          #somehow create newObject without calling __init__         newObject._Parameter = oldObject._Parameter         return newObject 

In other words, it is not possible to create an instance without passing the parameter file. In my "real" case, however, it is not a parameter file but some huge junk of data I certainly not want to carry around in memory or even store it to disc.

And since I want to return an instance of C from the method Load I do somehow have to call the constructor.

OLD EDIT:

A more complex example, which explains why I am asking the question:

class B(object):         def __init__(self, name, data):         self._Name = name         #do something with data, but do NOT save data in a variable      @staticmethod     def Load(self, file, newName):         f = open(file, "rb")         s = pickle.load(f)         f.close()          newS = B(???)         newS._Name = newName         return newS 

As you can see, since data is not stored in a class variable I cannot pass it to __init__. Of course I could simply store it, but what if the data is a huge object, which I do not want to carry around in memory all the time or even save it to disc?

like image 441
Woltan Avatar asked Jun 17 '11 09:06

Woltan


People also ask

Can I create a class without init?

We can create a class without any constructor definition. In this case, the superclass constructor is called to initialize the instance of the class. The object class is the base of all the classes in Python.

Can you have a Python class without init?

A͢J - S͟o͟l͟o͟H͟e͟l͟p͟e͟r͟ actually you can still create instances even if you don't explicitly define __init__(). I think in that case python implicitly uses the __init__() method of the (featureless) object class. In Python, the __init__() method plays the role of a constructor when creating an instance of a class.

Is __ init __ called automatically?

Use the __init__() method to initialize the object's attributes. The __init__() doesn't create an object but is automatically called after the object is created.

What is the correct way to instantiate a class in Python?

Instantiating a class in Python is simple. To instantiate a class, we simply call the class as if it were a function, passing the arguments that the __init__ method defines. The return value will be the newly created object.


2 Answers

You can circumvent __init__ by calling __new__ directly. Then you can create a object of the given type and call an alternative method for __init__. This is something that pickle would do.

However, first I'd like to stress very much that it is something that you shouldn't do and whatever you're trying to achieve, there are better ways to do it, some of which have been mentioned in the other answers. In particular, it's a bad idea to skip calling __init__.

When objects are created, more or less this happens:

a = A.__new__(A, *args, **kwargs) a.__init__(*args, **kwargs) 

You could skip the second step.

Here's why you shouldn't do this: The purpose of __init__ is to initialize the object, fill in all the fields and ensure that the __init__ methods of the parent classes are also called. With pickle it is an exception because it tries to store all the data associated with the object (including any fields/instance variables that are set for the object), and so anything that was set by __init__ the previous time would be restored by pickle, there's no need to call it again.

If you skip __init__ and use an alternative initializer, you'd have a sort of a code duplication - there would be two places where the instance variables are filled in, and it's easy to miss one of them in one of the initializers or accidentally make the two fill the fields act differently. This gives the possibility of subtle bugs that aren't that trivial to trace (you'd have to know which initializer was called), and the code will be more difficult to maintain. Not to mention that you'd be in an even bigger mess if you're using inheritance - the problems will go up the inheritance chain, because you'd have to use this alternative initializer everywhere up the chain.

Also by doing so you'd be more or less overriding Python's instance creation and making your own. Python already does that for you pretty well, no need to go reinventing it and it will confuse people using your code.

Here's what to best do instead: Use a single __init__ method that is to be called for all possible instantiations of the class that initializes all instance variables properly. For different modes of initialization use either of the two approaches:

  1. Support different signatures for __init__ that handle your cases by using optional arguments.
  2. Create several class methods that serve as alternative constructors. Make sure they all create instances of the class in the normal way (i.e. calling __init__), as shown by Roman Bodnarchuk, while performing additional work or whatever. It's best if they pass all the data to the class (and __init__ handles it), but if that's impossible or inconvenient, you can set some instance variables after the instance was created and __init__ is done initializing.

If __init__ has an optional step (e.g. like processing that data argument, although you'd have to be more specific), you can either make it an optional argument or make a normal method that does the processing... or both.

like image 143
Rosh Oxymoron Avatar answered Sep 21 '22 19:09

Rosh Oxymoron


Use classmethod decorator for your Load method:

class B(object):         def __init__(self, name, data):         self._Name = name         #store data      @classmethod     def Load(cls, file, newName):         f = open(file, "rb")         s = pickle.load(f)         f.close()          return cls(newName, s) 

So you can do:

loaded_obj = B.Load('filename.txt', 'foo') 

Edit:

Anyway, if you still want to omit __init__ method, try __new__:

>>> class A(object): ...     def __init__(self): ...             print '__init__' ... >>> A() __init__ <__main__.A object at 0x800f1f710> >>> a = A.__new__(A) >>> a <__main__.A object at 0x800f1fd50> 
like image 44
Roman Bodnarchuk Avatar answered Sep 18 '22 19:09

Roman Bodnarchuk