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:
- Support different signatures for
__init__that handle your cases by using optional arguments. - 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.
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:
- Support different signatures for
__init__that handle your cases by using optional arguments. - 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.
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>
Hello everyone!
While learning about classes in Python, I encountered the following two questions. Consider the following two classes:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = ageand
class Dog:
def dog_constructor(self, name, age):
self.name = name
self.age = age
The main difference is that the first class contains an __init__ method, but the second one does not.
To create an instance in the first class, I used: my_dog = Dog('Willie', 5). However,
for the second one I tried: my_dog = Dog.dog_constructor('Willie', 10) which did not work. Then eventually
I was told that I should use
my_dog = Dog()
my_dog.dog_constructor('Willie', 5).I am so confused about why we should use this approach.
Can anyone explain to me the importance of having an __init__ method in a class and why instances are created differently depending on whether we have __init__ or not?
I have been struggling with this for a while but still cannot grasp it.
I'd be very thankful for the explanation! Thank you!
When feasible, letting __init__ get called (and make the call innocuous by suitable arguments) is preferable. However, should that require too much of a contortion, you do have an alternative, as long as you avoid the disastrous choice of using old-style classes (there is no good reason to use old-style classes in new code, and several good reasons not to)...:
class String(object):
...
bare_s = String.__new__(String)
This idiom is generally used in classmethods which are meant to work as "alternative constructors", so you'll usually see it used in ways such as...:
@classmethod
def makeit(cls):
self = cls.__new__(cls)
# etc etc, then
return self
(this way the classmethod will properly be inherited and generate subclass instances when called on a subclass rather than on the base class).
A trick the standard pickle and copy modules use is to create an empty class, instantiate the object using that, and then assign that instance's __class__ to the "real" class. e.g.
>>> class MyClass(object):
... init = False
... def __init__(self):
... print 'init called!'
... self.init = True
... def hello(self):
... print 'hello world!'
...
>>> class Empty(object):
... pass
...
>>> a = MyClass()
init called!
>>> a.hello()
hello world!
>>> print a.init
True
>>> b = Empty()
>>> b.__class__ = MyClass
>>> b.hello()
hello world!
>>> print b.init
False
But note, this approach is very rarely necessary. Bypassing the __init__ can have some unexpected side effects, especially if you're not familiar with the original class, so make sure you know what you're doing.
Every class has an __init__ method. If it doesn't explicitly define one, then it will inherit one from its parent class. In your 2nd example, the class inherits __init__ and a bunch of other methods (and other non-method attributes) from the base object class. We can see that via the dir function:
class Dog:
def init_instance(self,name):
self.name = name
print('My name is',name)
print(dir(Dog))
output
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'init_instance']
__init__ gets called automatically after the instance is constructed (via the __new__ method), so we might as well use it if we need to initialize our instance. But we can call your init_instance explicitly:
bob = Dog()
bob.init_instance('Bob')
print(bob.name)
output
My name is Bob
Bob
If you give you class an initializer that isn't named __init__ then it won't get called automatically. How should Python know that that method is an initializer? Although it's customary to make __init__ the first method in the class definition, that's by no means mandatory, and some people like to put __init__ last.
You said: "I have seen code where the init method has not been used, how come?" Well, some classes simply don't need their instances to be initialized: their instance attributes are set via various other methods, or by direct assignment in code outside the class definition, eg bob.color = 'brown'. Or they inherit a perfectly usable __init__ from a parent class.
init is nothing else then a method to initially prepare the state of your object. In other languages they have similar concepts as Constructors and it's not necessarily needed.
I'm not aware of a way to create new instances of classic classes (which is what you used in your example) without calling __init__(). New instances of new-style classes (descendants of object) can be created using
object.__new__(cls)
where cls is the type of object you would like to create.
An alternative is to use copy.copy() for copying, possibly overwriting __getstate__() and __setstate__() to define what should be copied.
Edit: To create a new instance of a classic class cls without calling __init__(), you can use the following hack:
class EmptyClass:
pass
new_instance = EmptyClass()
new_instance.__class__ = cls
new_instance.__dict__.update(whatever)
Remember that every object has a attribute named __class__. If you do <object>.__class__ it, will return that object's class object (if that makes sense). The class object is callable so you can add parentheses to the end to create a new instance of that class.
newobj = self.__class__()
etree.parse is a Factory function. Their purpose is mainly to be convenient ways of constructing objects (instances). As you can easily verify by looking at the source, the parse function does almost exactly as you do in your second example except it ommits a line of code or two.
In this case, what's happening is that the etree.parse() function is creating the ElementTree object for you, and returning it. That's why you don't have to call a constructor yourself; it's wrapped up in the parse function. That function creates an ElementTree instance, parses the data and modifies the new object to correctly represent the parsed information. Then it returns the object, so you can use it (in fact, if you look at the source, it does essentially what you wrote in your second example).
This is a pretty common idiom in object-oriented programming. Broadly speaking, it's called a factory function. Basically, especially for complex objects, a lot of work is required to create a useful instance of the object. So, rather than pack a lot of logic into the object's constructor, it's cleaner to make one or more factory functions to create the object and configure it as needed. This means that someone developing with the library may have several clean, simple ways to instantiate the class, even if "under the hood" that instantiation may be complex.
From python documentation:
The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named init(), like this...
So __init__ isn't needed, it is the mechanism python provides to allow you to set an initial state of your object when it is initialized.
There is no need to create an __init__ function if you do not need to do any initialization other than that provided by the parent class. Note that __init__ functions of any parent class do get called automatically:
In [1]: class Parent(object):
...: def __init__(self):
...: print 'Inside __init__ of parent'
In [2]: class Person(Parent):
...: def run(self):
...: print 'I am a person'
In [3]: p = Person()
Inside __init__ of parent
In [4]: p.run()
I am a person
In modern Python, any class implicitly derives from the object class, which supposedly takes care of basic things like allocating memory space, even if you do not add any other properties.
You should be able to directly invoke the tp_new of Foo (equivalent to invoking Foo.__new__ at the Python layer). That will perform the allocation and C level "mandatory initialization" work, without the "optional initialization" work of tp_init/__init__. It's the same strategy pickle uses to create instances of a type without initializing them (so it can fill them in via __setstate__ or directly filling in __dict__, as appropriate).
Assuming Foo is a C level PyTypeObject*, something like this should do the trick:
auto emptytup = PyTuple_New(0); /* AFAICT, the args tuple is mandatory, but kwargs is optional */
/* Error check for PyTuple_New failure */
auto obj = Foo->tp_new(Foo, emptytup, NULL);
Py_DECREF(emptytup);
/* Error check for new fail */
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)
Make self.bar a property that creates the instance the first time it's needed.
class Foo:
def __init__(self, bar=None):
self._bar = bar
@property
def bar(self):
if self._bar is None:
self._bar = CreateBarObject(...)
return self._bar
The instance is fully functional. The instance's bar property will create the Bar object the first time it's needed. Or you can set _bar from the C API before that, and that'll be used instead. Or you can pass in an existing Bar object when instantiating the class. Your choice.