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).
Answer from Alex Martelli on Stack OverflowHello 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.
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>
class Student()
...
def main():
Student = getStudent()
print(f"{Student.name} lives in {Student.house})"
def getStudent():
Student.name = input("enter name: ")
Student.house = input("enter house: ")
return StudentIt appears that indeed a class named Student is created above. Fail to understand how a class can be created without use of __init__. If indeed a class can be created without __init__, what is the purpose of __init__.
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.
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")
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.
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.
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__()
In Python you can add members dynamically to an object, but (1) the name must already exist (it must have been assigned) and (2) it must be bound to an instance of some class. To do so you may create an empty class:
class Empty:
pass # empty statement otherwise the class declaration cannot succeed
construct an instance of it and assign it to your variable
person = Empty()
and then add whatever data you want
person.name = 'Mike'
person.age = 25
person.gender = 'male'
On the other hand, if you don't need the additional features a "normal" class provides and you just want to store some data in a key=>value fashion you should probably just use a dictionary.
person={}
person['name']='Mike'
person['age']=25
person['gender']='male'
(notice that, at least up to Python 2.7, this is mostly just a stylistic/syntactic difference, since instance members are implemented underneath in terms of dictionaries)
As a general guideline, you want classes when you are instantiating multiple objects made in the same way (and where typically the assignment to the members is done in the class constructor; adding members later generally makes for difficult to follow code), dictionaries otherwise.
Python won't magically create a container object when you start assigning attributes to it, and if matlab allows this, I'd consider matlab badly broken. Consider this:
person.name = "Mike"
persom.age = 25
person.sex = "Male"
Now we have two objects, person and persom, and person doesn't have age, and there was no hint that this happened. Later you try to print person.age and, one would hope, matlab then complains... two pages after the actual mistake.
A class can itself be used as a container or namespace. There's no need to instantiate it, and it'll save you a bit of typing if you just want a bundle of attributes.
class sex:
male = "M"
female = "F"
class person:
name = "Mike"
age = 25
sex = sex.male
To access or modify any of these, you can use person.name, etc.
N.B. I used a class for sex as well to illustrate one of the benefits of doing so: it provides consistency in data values (no remembering whether you used "M" or "Male" or "male") and catches typos (i.e. Python will complain about sex.mlae but not about the string "mlae" and if you were later checking it against "male" the latter would fail).
Of course, you still run the risk of misspelling name, age, or sex in this type of class definition. So what you can do is use the class as a template and instantiate it.
class Person:
def __init__(self, name, age=None, sex=None):
self.name, self.age, self.sex = name, age, sex
Now when you do:
person = Person("Mike", 25, sex.male)
or if you want to document what all those parameters are:
person = Person("Mike", age=25, sex=sex.male)
it is pretty much impossible to end up with an object that has a misspelled attribute name. If you mess it up, Python will give you an error message at the point you made the mistake. That's just one reason to do it this way.
I'm working with Flask and using SQL Alchemy ORM and there is something I would like to understand in the code. SQLAlchemy allows the creation of model class by extending the db.Model And in the model class we declare class attributes instead of instance attributes. Why is that ?
We don't even have a constructor or __init__ method and yet we are able to create objects by passing arguments (and that too on the freaking class attributes). How is this working ?
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(name) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' db = SQLAlchemy(app)
class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(20), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return f"User('{self.username}', '{self.email}')"with app.app_context(): db.create_all()
# how is the user getting created here with any init method in the User class user1 = User(username="foo", email="foo@demo.com", password="foobar") print(user1) db.session.add(user1) db.session.commit() print(User.query.all())