Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

boi
boi
14,242 Points

Python OOP, Can't understand the __new__ method.

Hello there, How are you?

The __new__ method is a little confusing to me, Kenneth explains that the __new__ method takes no "self" argument but if you take a look at the code below;

class ReversedStr(str):

    def __new__(value):
        not_self = str.__new__(value)
        not_self = not_self[::-1]
        return not_self

Str = Reversedstr("hello")
#output TypeError: __new__() takes 1 positional argument but 2 were given                                                

Now to try with "self"

class ReversedStr(str):

    def __new__(self,value):
        not_self = str.__new__(self,value)
        not_self = not_self[::-1]
        return not_self

Str = Reversedstr("hello")

#output  "olleh"  what is expected to be

let's take a look at another example;

class ReversedStr(str):

    def __new__(value):
        not_self = value[::-1]
        return not_self

Str = Reversedstr("hello")

#output TypeError: __new__() takes 1 positional argument but 2 were given
class ReversedStr(str):

    def __new__(self,value):   #inserted "self" here or 2 positional arguments
        not_self = value[::-1]
        return not_self

Str = Reversedstr("hello")
#output as expected "olleh"  works perfectly.

Maybe the real question is that why does the __new__ method require two positional arguments? or why does it need that first argument?


Just another quick question, please.

I read that the use of the super method;

not_self = str.__new__(self,value)

is important because it makes use of the builtin converters in store for us, an example;

 def __new__(self,value):

        not_self = value[::-1]
        return not_self

Str = Reversedstr(12345) #an int
#output TypeError: 'int' object is not subscriptable 

def __new__(self,value):
        not_self = str.__new__(self,value)
        not_self = not_self[::-1]
        return not_self

Str = Reversedstr(12345)
#output (54321) as expected

Is there any way I can see these built-in converters? I tried using help(ReversedStr) but I could not spot anything similar.

Steven Parker
Steven Parker
231,261 Points

Can you provide a link to the video and an approximate time reference?

1 Answer

Steven Parker
Steven Parker
231,261 Points

The method "__new__" is a class method, so you (and Kenneth) are right that it takes no "self" argument, but it does take a "cls" argument. That accounts for the extra item being passed. It would just be more conventional to name that first argument "cls" instead of "self", since it's not an instance.

This may be covered in the video in another form (you forgot to provide a link to the video).

boi
boi
14,242 Points

Here is the link Built-ins, also I understand that __new__ is a class method, but why didn't Kenneth use cls ? and used *args and **kwargs?

Steven Parker
Steven Parker
231,261 Points

Since "*args" is being used, then "cls" will be taken as args[0]. Since it's not being used directly, it's easier to just take all the arguments together and pass them along to the base class.

Your version just handles the arguments individually instead of in bulk.

boi
boi
14,242 Points

Thanks for the answer, it explains the first question, could you please check out my second question? will give you best answer promise.

Steven Parker
Steven Parker
231,261 Points

The source code for Python is available at python.org.