Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__new__ and __init__ in Python

Tags:

python

class

I am learning Python and so far I can tell the things below about __new__ and __init__:

  1. __new__ is for object creation
  2. __init__ is for object initialization
  3. __new__ is invoked before __init__ as __new__ returns a new instance and __init__ invoked afterwards to initialize inner state.
  4. __new__ is good for immutable object as they cannot be changed once they are assigned. So we can return new instance which has new state.
  5. We can use __new__ and __init__ for both mutable object as its inner state can be changed.

But I have another questions now.

  1. When I create a new instance such as a = MyClass("hello","world"), how these arguments are passed? I mean how I should structure the class using __init__ and __new__ as they are different and both accepts arbitrary arguments besides default first argument.
  2. self keyword is in terms of name can be changed to something else? But I am wondering cls is in terms of name is subject to change to something else as it is just a parameter name?

I made a little experiments as such below:

>>> class MyClass(tuple):     def __new__(tuple):         return [1,2,3] 

and I did below:

>>> a = MyClass() >>> a [1, 2, 3] 

Albeit I said I want to return tuple, this code works fine and returned me [1,2,3]. I knew we were passing the first parameters as the type we wanted to receive once the __new__ function is invoked. We are talking about New function right? I don't know other languages return type other than bound type?

And I did anther things as well:

>>> issubclass(MyClass,list) False >>> issubclass(MyClass,tuple) True >>> isinstance(a,MyClass) False >>> isinstance(a,tuple) False >>> isinstance(a,list) True 

I didn't do more experiment because the further wasn't bright and I decided to stop there and decided to ask StackOverflow.

The SO posts I read:

  1. Python object creation
  2. Python's use of __new__ and __init__?
like image 723
Tarik Avatar asked Nov 12 '11 19:11

Tarik


People also ask

What is __ new __ in python?

The __new__() is a static method of the object class. When you create a new object by calling the class, Python calls the __new__() method to create the object first and then calls the __init__() method to initialize the object's attributes.

What is __ init __ () in python?

The __init__ method is the Python equivalent of the C++ constructor in an object-oriented approach. The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.

Is __ new __ constructor?

TLDR; __init() is not the constructor, __new__() is. Generally, developers new to python are told that __init__() method is called the constructor.

What is __ init __ and self in python?

The self in keyword in Python is used to all the instances in a class. By using the self keyword, one can easily access all the instances defined within a class, including its methods and attributes. init. __init__ is one of the reserved methods in Python. In object oriented programming, it is known as a constructor.


1 Answers

how I should structure the class using __init__ and __new__ as they are different and both accepts arbitrary arguments besides default first argument.

Only rarely will you have to worry about __new__. Usually, you'll just define __init__ and let the default __new__ pass the constructor arguments to it.

self keyword is in terms of name can be changed to something else? But I am wondering cls is in terms of name is subject to change to something else as it is just a parameter name?

Both are just parameter names with no special meaning in the language. But their use is a very strong convention in the Python community; most Pythonistas will never change the names self and cls in these contexts and will be confused when someone else does.

Note that your use of def __new__(tuple) re-binds the name tuple inside the constructor function. When actually implementing __new__, you'll want to do it as

def __new__(cls, *args, **kwargs):     # do allocation to get an object, say, obj     return obj 

Albeit I said I want to return tuple, this code works fine and returned me [1,2,3].

MyClass() will have the value that __new__ returns. There's no implicit type checking in Python; it's the responsibility of the programmer to return the correct type ("we're all consenting adults here"). Being able to return a different type than requested can be useful for implementing factories: you can return a subclass of the type requested.

This also explains the issubclass/isinstance behavior you observe: the subclass relationship follows from your use of class MyClass(tuple), the isinstance reflects that you return the "wrong" type from __new__.

For reference, check out the requirements for __new__ in the Python Language Reference.

Edit: ok, here's an example of potentially useful use of __new__. The class Eel keeps track of how many eels are alive in the process and refuses to allocate if this exceeds some maximum.

class Eel(object):     MAX_EELS = 20     n_eels = 0      def __new__(cls, *args, **kwargs):         if cls.n_eels == cls.MAX_EELS:             raise HovercraftFull()          obj = super(Eel, cls).__new__(cls)         cls.n_eels += 1         return obj      def __init__(self, voltage):         self.voltage = voltage      def __del__(self):         type(self).n_eels -= 1      def electric(self):         """Is this an electric eel?"""         return self.voltage > 0 

Mind you, there are smarter ways to accomplish this behavior.

like image 92
Fred Foo Avatar answered Sep 18 '22 21:09

Fred Foo