How does everything work, even an object?

I understand the basic theory behind all that is an Object, but I really do not understand how this is implemented under the hood.

Functions

So: foo(4) same as foo.__call__(4) . But what prevents me from doing foo.__call__.__call__(4) ?

foo is a function, and foo.__call__... is all the wrappers of the methods around the function, but when I call the function, which one is even called?

All these properties

My foo function has many properties, and each of these objects stores many properties, so how does it not take up infinite memory?

sys.getsizeof('a') creates 22 , which seems pretty big for a single character, but pretty small as it refers to 71 properties.

I assume I am asking if I want to implement a naive version of python (I am not, but this is the best way to ask), how would I implement this?

Edit 1 I looked at the built-in a bit and realized that they refer to the same properties ( id('a'.upper) == id('b'.upper) ). What makes me ask how he knows which object he is accessing?

Edit 2 As indicates, indicates < to clear this.

I looked at the source for IronPython , as I thought it would help me understand, but it confused me even more.

+7
python oop
source share
4 answers

I think you are confused that although all Python variables can be objects, and all the properties of these variables can be objects, there is a limit. I mean, for a regular class, a structure usually goes:

 myclass -> classobj -> type 

which you can see if you try this in the console:

 >> class A: .. pass .. >> print type(A) <type 'classobj'> >> print type(type(A)) <type 'type'> 

but if you try to go deeper than type , you just get type . type is the base object for all objects in Python.

 >> print type(type(type(A))) <type 'type'> >> print type(type(type(type(type(A))))) <type 'type'> 

You get not only the same base class / object type, but you get the same instance of this type for an instance of class A, therefore, although you can do an infinite recursion of the type function (i.e. type(type(type(type(... )))) ), you won’t go anywhere (that is, you will not explore the bottomless pit of infinite memory).

 >> id(type(type(type(A))) 505578544 >> id(type(type(type(type(A)))) 505578544 

The same principle applies to all objects in Python and all properties of objects in Python, since they are also objects, but they are all finite.

Answering one of your previous questions,

foo.__call__ is the same instance of the wrapper method as foo.__call__.__call__

So, nothing prevents you from making a very long line with foo.__call__.__call__.__call__ ...

Python plays the trick with you in that foo.__call__ provides an instance for the wrapper method, and inside this wrapper method class there is a function / variable, also called __call__ , which points to the same instance of this class.

+10
source share

Your assumption is that if everything is an object, foo(4) should automatically translate to foo.__call__(4) , this is wrong.

Python can first check if the foo object is a function, and if so, in other cases (for example, look for the __call__ attribute).

+2
source share

You can think of an “object” as a pointer to its data member dictionary and a pointer to its data element dictionary type (usually including type methods). Usually this is finite space, and the type dictionary is shared by all objects of this type. (This is an oversimplification, but probably good enough to understand why it is not an infinite memory).

+1
source share

The id anomaly is caused by early reference counting: the Python memory manager releases 'a'.upper too soon, and then 'b'.upper gets allocated to the same memory address.

Early free:

 >>> id('a'.upper), id('b'.upper) (3073677900L, 3073677900L) 

Without early free:

 >>> x, y = 'a'.upper, 'b'.upper >>> id(x), id(y) (3073678252L, 3073677900L) >>> x, y (<built-in method upper of str object at 0xb7317b20>, <built-in method upper of str object at 0xb7317b40>) 

Link comparison:

 >>> 'a'.upper is 'b'.upper False 
+1
source share

All Articles