36

Could anybody explain whether it is safe to reinitialize an object by calling "self.init(". as shown in the following simplified example?

The reason i'm asking is that i couldn't find this method neither in several python books nor in internet. There are some who suggest to list all attributes and set them to initial value one by one. Basically i want to set my object to initial state after it has finished some tasks.

class Book(object):
    def __init__(self,name,author):
        self.name = name
        self.author = author
        self.copies = 5

    def reset(self):
        self.__init__(self.name,self.author)

    def incrementCopy(self):
        self.copies += 1

Kite = Book('kite runner','khaled hosseini')

print 'initial number of copies:', Kite.copies
Kite.incrementCopy()
Kite.incrementCopy()
Kite.incrementCopy()
print '3 copies are added:', Kite.copies
Kite.reset()
print 'number of copies are reinitialized', Kite.copies


initial number of copies: 5
3 copies are added: 8
number of copies are reinitialized 5
  • 2
    Why can't you do that in `reset` function itself, after you will have to pass the initial values again? `self.name` and `self.author` accesses the current value, not the initial. – Rohit Jain Oct 26 '12 at 17:02
  • self.name and self.author are not going to be changed, they can be ignored in this example. My question is about self.__init__ part. I didn't quite understand your question. What do you mean by "that"? –  Oct 26 '12 at 17:09

3 Answers3

38

The only thing special about __init__ is that it is called automatically when an instance is created. Other than that it is a normal method, and it is safe to use it to set your object back to its initial state.

That being said, just because it is safe doesn't mean it is a good idea. Other people looking at your code might be confused by it, and it isn't difficult to do everything in a reset method (that __init__ can even call) to be more explicit about how the method is being used.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
32

I would consider it a very bad practice - you should not __init__ manually (unless calling __init__ of the parent class). Also, passing object's data back to __init__ is somewhat strange.

Why not something like this:

class Book(object):
    def __init__(self,name,author):
        self.name = name
        self.author = author
        self.reset()

    def reset(self):
        self.copies = 5
Code Painters
  • 7,175
  • 2
  • 31
  • 47
  • 7
    +1. The standard solution (not just in Python, but in most languages with constructors) is to factor out the code needed by both the constructor and the regular function(s). – abarnert Oct 26 '12 at 18:13
  • 9
    Only problem with this is I get code lint warnings: "Instance attribute copies defined outside of __init__" – Greg Sep 12 '17 at 18:41
  • 2
    yeah, recommended way seems to be to create all the attributes in `__init__`, frankly speaking I prefer to ignore it and avoid duplication. – Code Painters Sep 22 '17 at 13:15
6

I consider is not unsafe, I have used it and nothing strange happens in the memory, but take into account that attributes defined in other methods will not be reset. Consider for example:

class Dummy:
    def __init__(self):
        self.x = 4
    def plus_one(self):
        self.x += 1
    def define_other_variables(self):
        self.y = 3
    def reset(self):
        self.__init__()
D = Dummy()
print(D.x) # 4
# print(D.y) will raise an AttributeError
D.plus_one()
D.plus_one()
# D.y do not exist
D.define_other_variables()
# D.y exist
print(D.x) # 6
D.reset()
print(D.x) # 4
print(D.y) # 3, still exist!!

Then, just remember to define every object in the init function. you could consider bad practice for this reason but I still think is elegant.

Toby Petty
  • 4,431
  • 1
  • 17
  • 29
user10369452
  • 71
  • 1
  • 1