Python: Old-style to New-style Class Conversion Causes Error

In summary: This is really confusing! self.append(temp);#append the temp list to the grid class, overwriting the existing temp list! # Other methods that aren't being used and aren't in the trace.test = grid(2);It works perfectly like this. When I substitute __new__ for __init__, I get this:Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\
  • #1
TylerH
729
0
I'm trying to convert my __init__ to __new__, but I can't find any docs on how the syntax differs or anything really, that pertains to how this bug could be caused by it. What am I doing wrong here?

Code:
import copy;

class grid(list):
    def __new__(self, size):
        self.size = size;
        for i in range(size):
            temp = list();
            for j in range(size):
                temp.append(False);
            self.append(temp);

# Other methods that aren't being used and aren't in the trace.

test = grid(2);
It works perfectly like this. When I substitute __new__ for __init__, I get this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 487, in runfile
execfile(filename, namespace)
File "C:\Python27\Scripts\Grid\grid.py", line 64, in <module>
test = grid(2);
File "C:\Python27\Scripts\Grid\grid.py", line 10, in __new__
self.append(temp);
TypeError: append() takes exactly one argument (0 given)

Thanks for your time and help,
Tyler
 
Technology news on Phys.org
  • #2
TylerH said:
I'm trying to convert my __init__ to __new__
Why do you want to do that? __new__ and __init__ are different things. __new__ is a static method. It does not take self as an argument; self doesn't exist yet. The __new__ method instead takes the class as its first argument and creates (but does not necessarily initialize) a new instance of the class. The __new__ method returns this newly created instance.

Initializing a new member of a class is a job of the __init__ method.
but I can't find any docs on how the syntax differs
http://docs.python.org/2/reference/datamodel.html#object.__new__

Note the final paragraph on __new__:
__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.​
You normally don't override __new__.
 
  • #3
Why would you change __init__() to __new__(). Bad idea! They are not the same and init is the way to go! __new__() is an ugly hack to make inheritance from immutable types work.

Normal inheritance works like this:

Code:
class a:
   def __init__(self,par):
      self.foo=par
   
   def somefunction(self):
      print "wakka wakka "+str(self.foo)

class b(a):
   def __init__(self,par1,par2):
      self.foo=par1
      self.bar=par2
   
   def someotherfunction(self):
      self.somefunction()
      print "wikki wikki "+str(self.bar)

so b can access the methods of a

Code:
>>> x=b("gaga","haha")
>>> x.someotherfunction()
wakka wakka gaga
wikki wikki haha
>>> x.somefunction()
wakka wakka gaga

Class declarations are also objects and you can modify them. For example if you want to know how many instances of class b have ever been created you could put a counter in b
Code:
>>> class b(a):
...    def __init__(self,par1,par2):
...       b.instance_counter+=1
...       self.foo=par1
...       self.bar=par2
... 
>>> b.instance_counter=0
>>> 
>>> e=b("","")
>>> f=b("","")
>>> g=b("","")
>>> print b.instance_counter
3

You see that instance_counter is a member of b not of any instance of b. You can also add functions that are not member functions (without "self") to b this way.

So what happens when you create a class instance, is that python builds some empty object with the respective member functions, and hands it to the __init__() function, and then it can get modified by init. With immutable types __init__() cannot do its job. After python has created the immutable object, init functions cannot modify it anymore. So __new__() was invented which steps in before init. And it does not receive a pre build self object but a class! So when you use __new__(), you call __new__() of the immutable type that you want to inherit from, giving it the unchangeable value that you want. When you are done creating that object __init__ gets called with the created object as self.

Let's go through your code:
Code:
import copy;#you don't use copy anywhere in your example

class grid(list):
    def __new__(self, size): #self points to the class grid now not to any object
        self.size = size; #add a size variable to grid class declaration just like instance_number
        for i in range(size):
            temp = list(); # Aaaargh why do you use semicolons this is not c!
            for j in range(size):
                temp.append(False); #fill the list with False
            self.append(temp);  #call the function grid.append() I don't even know what it is
                                 # it is not an object of grid but the of the grid declaration itself!

To make a long argument short. Just don't ever use __new__() it's for people who smell of java, and think sub classing integers is cool.
 
  • #4
I use the copy module later, in code I removed to reduce the amount you have to read. [STRIKE]The reason I'm using new at all is because I read that __init__ is going to be removed in 3.0+.[/STRIKE]
EDIT: Nevermind. Either I misunderstood what I read or I didn't remember it correctly. I now know that __init__ isn't depreciated in 3+
[STRIKE]So, if this is my class, how do I make it 3+ compatible?[/STRIKE]
Code:
class grid(list):
    def __init__(self, size):
        self.size = size;
        for i in range(size):
            temp = list();
            for j in range(size):
                temp.append(False);
            self.append(temp);

Also, just for the sake of understanding (I get that it almost always isn't pythonic), how would you use __new__ to, eg, subclass string or some other immutable type.
 
Last edited:

1. What is the difference between old-style and new-style classes in Python?

The main difference between old-style and new-style classes in Python is the way they handle inheritance. Old-style classes use a linear search algorithm for method resolution, while new-style classes use a more efficient method resolution order (MRO) algorithm. Additionally, new-style classes offer more features such as properties and descriptors.

2. Why does converting from an old-style to a new-style class in Python sometimes cause an error?

This error can occur when attempting to convert a class that inherits from multiple base classes. Since old-style classes use a linear search algorithm for method resolution, they do not support multiple inheritance. Therefore, converting to a new-style class may cause conflicts in the method resolution order and result in an error.

3. How can I check if my class is an old-style or a new-style class in Python?

To check if a class is an old-style or a new-style class, you can use the built-in function type() and pass in an instance of the class as an argument. If the class is a new-style class, the returned type will be type. If it is an old-style class, the returned type will be classobj.

4. Can I convert an old-style class to a new-style class without causing an error?

In most cases, yes. If the old-style class inherits from a single base class and does not use any unsupported features, then converting to a new-style class should not cause an error. However, if the class inherits from multiple base classes or uses unsupported features, it may result in an error.

5. Is it recommended to convert old-style classes to new-style classes in Python?

Yes, it is generally recommended to convert old-style classes to new-style classes in Python. New-style classes offer more features and improved functionality, as well as being more efficient in terms of method resolution. Additionally, Python versions 3.X only support new-style classes, so conversion may be necessary for compatibility.

Similar threads

  • Programming and Computer Science
Replies
17
Views
2K
  • Programming and Computer Science
Replies
6
Views
5K
  • Programming and Computer Science
Replies
4
Views
2K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
1
Views
3K
  • Programming and Computer Science
Replies
1
Views
2K
Back
Top