In learning about Python’s data model, I am playing with creating objects from existing objects using the __new__ method. Here are some examples which create new objects of various types:
x = 2; print type(x).__new__(x.__class__)
x = {}; print type(x).__new__(x.__class__)
x = [1,2]; print type(x).__new__(x.__class__)
x = 2.34; print type(x).__new__(x.__class__)
x = '13'; print type(x).__new__(x.__class__)
x = 1.0j; print type(x).__new__(x.__class__)
x = True; print type(x).__new__(x.__class__)
x = (1,2); print type(x).__new__(x.__class__)
However, the following three experiments give me errors:
x = None; print type(x).__new__(x.__class__)
x = lambda z: z**2; print type(x).__new__(x.__class__)
x = object; print type(x).__new__(x.__class__)
The errors are (respectively):
TypeError: object.__new__(NoneType) is not safe, use NoneType.__new__()
TypeError: Required argument 'code' (pos 1) not found
TypeError: type() takes 1 or 3 arguments
Why don’t these three examples work? (Note: for the lambda example it appears that I have to pass in a code fragment when I invoke the __new__ method but I don’t know how to do that.) I am using Python 2.6.
Please note that I realize this is not necessarily the way you would want to create new objects in real code, but my purpose is not practical, rather, it is to understand how the low-level object methods work.
It’s nothing too special, it’s just that for some types there is a default “empty” object of that type, while for others there is not. Your working examples are basically equivalent to:
. . . all of which work. Your last three examples are basically trying to create new instances of NoneType,
function, andtype.types.NoneType()you’ll get a more direct message saying “Can’t create NoneType instances”.)functionfails because, as you saw, it requires an argument, and you don’t provide one. What you’d need is a code object, which you could get from an existing function or from thecompilefunction. (It also requires aglobalsargument, which can just be a dict.)typefails because you didn’t give enough arguments. You can either dotype(foo)to get the type of foo, ortype(name, bases, dict)to create a new type (i.e., a class).Notice incidentally that in your last example you are taking the type of
object, which is itself a type. If you dox = object()instead (making x be an individual object rather than the object type) then it will work and create a “blank” object.The thing to remember is that calling
__new__is not really that magical. It is just what happens when you directly try to instantiate the type by doingsomeType(). If that type requires arguments, calling__new__will fail, just like any other function call will fail if you don’t give it the right arguments, becausetype(x).__new__is just a function like any other function. You can see this with a user-defined class:It succeeded in the first case, because my class didn’t require arguments; it failed in the second class, because the second class does require arguments.
The
__new__does not fail for any secret reason; it just fails because the type you are trying to instantiate requires arguments in order to construct an instance. (TheNonecase is the only one that’s different here; that one does fail for a special reason, becauseNoneis a special object in Python.)