我理解Everything背后的主要理论是一个对象,但我真的不明白它是如何在幕后实现的.
所以:foo(4)是一样的foo.__call__(4).但是阻止我做什么foo.__call__.__call__(4)呢?
foo是一个函数,并且foo.__call__...是函数的所有方法包装器,但是当我调用一个函数时,甚至调用了哪些函数?
我的函数foo有很多属性,而且每个对象都存储了很多属性,那么它如何不占用无限的内存呢?
sys.getsizeof('a')产生22,对于一个角色看起来相当大,但是因为它引用了71个属性而非常小.
我想我要问的是,如果我想实现一个天真的python版本(我不是,但它似乎是最好的问题)我将如何实现它?
编辑1
我对builtins有点了解并意识到它们引用了相同的属性(id('a'.upper) == id('b'.upper)).这让我问它是如何知道它正在访问的对象?
编辑2正如pts指出的那样 'a'.upper is not 'b'.upper,以便清除它.
我看过IronPython的来源,因为我认为它会帮助我理解,但它让我更加困惑.
cra*_*ish 10
我认为你感到困惑的是,尽管Python的所有变量都可能是对象,并且这些变量的所有属性都可能是对象,但是存在限制.我的意思是,对于正常的类,结构通常是:
myclass -> classobj -> type
Run Code Online (Sandbox Code Playgroud)
如果你在控制台中尝试这个,你可以看到:
>> class A:
.. pass
..
>> print type(A)
<type 'classobj'>
>> print type(type(A))
<type 'type'>
Run Code Online (Sandbox Code Playgroud)
但如果你试着去深入type,你就会得到type.type是Python中所有对象的基础对象.
>> print type(type(type(A)))
<type 'type'>
>> print type(type(type(type(type(A)))))
<type 'type'>
Run Code Online (Sandbox Code Playgroud)
您不仅获得相同的基类/对象类型,而且您为A的类实例获得该类型的相同实例,因此尽管您可以对函数执行无限递归type(即.type(type(type(type(... ))))),但您不会去任何地方(即没有探索无限记忆的无底洞.)
>> id(type(type(type(A)))
505578544
>> id(type(type(type(type(A))))
505578544
Run Code Online (Sandbox Code Playgroud)
同样的原则适用于Python中的所有对象以及Python中对象的所有属性,因为它们也是对象,但它们都是有限的.
回答你之前的一个问题,
foo.__call__是'method-wrapper'的相同实例foo.__call__.__call__
所以没有什么能阻止你做一个很长的路线foo.__call__.__call__.__call__......
Python为你foo.__call__提供了一个技巧,它为'method-wrapper'提供了一个实例,而在'method-wrapper'类中,还有一个函数/变量,它也__call__指向该类的同一个实例.