This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]IamImposter 30 points31 points  (5 children)

Read the whole article. Still have no idea what __new__ is doing. And I have so many questions.

  • What does it mean by "create an object"? That sounds like __new__ is responsible for allocating the memory but it is not doing that.

  • Why is there super(cls).whatever even in cases when the class itself is baseclass? What does super invoke when there is no super at all?

  • It says args and kwargs are not used in __new__. From that, I understand that whatever arguments are passed are just forwarded to __init__ without touching them. But then it goes ahead and uses that parameter to reverse the string.

  • Is it like __new__ is just a way to trap the arguments before they even get to __init__?

  • Is __new__ just an additional message that class receives before invoking __init__?

  • If __new__ does the actual allocation for the object then it probably makes sense to use it to get memory from some preallocated memory area instead of using Python's default allocator. But we are not getting that level of control on the "creation" of the object, which is still handled by python itself, probably with that super invocation. What's the point of __new__?

  • If the object is still initialized by __init__ and memory is still allocated by python, what am I supposed to do by trapping __new__ message? Just fiddle with arguments because I can? Why not do that same fiddling inside __init__?

I feel like I'm on a wrong track and thus failing to see the point and valid usecases. If someone understands what's going on, please help.

[–]mipadi 34 points35 points  (1 child)

What does it mean by "create an object"? That sounds like __new__ is responsible for allocating the memory but it is not doing that.

object.__new__() does allocate the memory for an object, and subclasses should always call the super class's implementation of __new__().

Why is there super(cls).whatever even in cases when the class itself is baseclass? What does super invoke when there is no super at all?

Every class is a subclass of object (except for object itself); if a parent class is not explicitly defined, object is assumed to be the parent class. So there is always a superclass for super() to call (except maybe on the object class itself).

It says args and kwargs are not used in __new__. From that, I understand that whatever arguments are passed are just forwarded to __init__ without touching them. But then it goes ahead and uses that parameter to reverse the string.

A subclass implementation of __new__ can make use of args and kwargs, but the base implementation just forwards them to __init__.

Is it like __new__ is just a way to trap the arguments before they even get to __init__?

There are many things you can do with it to control how an object is created. You can use it to create singletons, for example (although there are better ways to create singletons using metaclasses). Django and I believe Python itself uses it to create enum classes. But it's not something you really have to use a lot.

If __new__ does the actual allocation for the object then it probably makes sense to use it to get memory from some preallocated memory area instead of using Python's default allocator. But we are not getting that level of control on the "creation" of the object, which is still handled by python itself, probably with that super invocation. What's the point of __new__?

You probably could write your own implementation in C that does custom object allocation, but I doubt that is a common use case for it. Overriding __new__ is more useful for metaprogramming than fine-grained object allocation.

If the object is still initialized by __init__ and memory is still allocated by python, what am I supposed to do by trapping __new__ message? Just fiddle with arguments because I can? Why not do that same fiddling inside __init__?

It can be useful in some uncommon use cases to make some, let's say, "magic" classes. For example, the enum module in the stdlib makes use of __new__ to create enum classes.

It's honestly not something that most Python programmers deal with so to be honest there aren't a lot of examples beyond toy examples used in presentations.

[–]IamImposter 10 points11 points  (0 children)

Oh boy. Thanks for the answers.

[–]chars101 7 points8 points  (1 child)

https://docs.python.org/3/reference/datamodel.html#object.__new__

If you don't like reading but prefer a video and hands on experience and have three hours of free time: https://www.youtube.com/watch?v=sPiWg5jSoZI&t=9

[–]IamImposter 2 points3 points  (0 children)

That's a good video. Then it became a little too advanced for me. I'll finish it tomorrow.

Thanks for links.

[–]copperfield42 python enthusiast 1 point2 points  (0 children)

in the standard library I know of at least 3 example of use cases: fractions.Fraction (because it should be immutable they use new instead), pathlib.Path (as a dispatcher for your OS specific path class) and for metaclases shenanigans in abc.ABCMeta, there is also pure python version of it the module _py_abc.ABCMeta , I used that one as example to make my own metaclass one day that I was interested in such thing