2024-04-24 10:36:04 发布
网友
我可以创建这样的python对象
class Test: pass t1 = Test() t1.var = "value" t1.num = 100
并且可以使用
print(t1.__dict__) # prints {'var': 'value', 'num': 100}
这是否意味着python对象在内部存储为字典?你知道吗
不是。但是在内部,所有Python对象(除了那些用__slots__或Python内置定义的对象)都使用字典进行动态属性访问。你知道吗
__slots__
正如您在下面的示例中所看到的,使用__slots__会使类型不存储内部字典,这会阻止为类型动态设置方法、字段或其他信息。但是,类型的大小因此而减小。你知道吗
In [7]: class A: ...: __slots__ = ('fields') ...: def __init__(self): ...: self.fields = 1 ...: In [9]: dir(A) Out[9]: ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'fields']
如果您查看一下CPython源代码code,您还将看到大多数内置类型都没有存储为字典,或者:
#ifndef Py_LIMITED_API typedef struct { PyObject_HEAD double ob_fval; } PyFloatObject; #endif
为了理解为什么所有允许动态设置变量、方法和其他信息的类都在内部使用dict来存储这些信息,我们需要考虑哪些字典非常擅长:O(1)通过O(1)插入和删除来访问信息。由于解释器在运行时之前不知道类可能具有哪些属性,如果该属性是变量、方法等,则需要在运行时使用绑定到类的某种容器。在其他语言中,如C++,这是通过使用函数指针数组(通常是不保证的)或虚拟表来实现的,允许您动态地将预定义的方法集更改为类。但是,由于方法名已经硬编码,因此不允许动态地向类中添加或删除方法。除了hashmap或二进制搜索树之外的任何方法都可能无法有效地允许动态类型。你知道吗
O(1)
基本上,是的。最好不要这样做。使用__slots__来最小化类的大小。你知道吗
简单的解释
不是。但是在内部,所有Python对象(除了那些用
__slots__
或Python内置定义的对象)都使用字典进行动态属性访问。你知道吗正如您在下面的示例中所看到的,使用
__slots__
会使类型不存储内部字典,这会阻止为类型动态设置方法、字段或其他信息。但是,类型的大小因此而减小。你知道吗如果您查看一下CPython源代码code,您还将看到大多数内置类型都没有存储为字典,或者:
基本原理
为了理解为什么所有允许动态设置变量、方法和其他信息的类都在内部使用dict来存储这些信息,我们需要考虑哪些字典非常擅长:
O(1)
通过O(1)
插入和删除来访问信息。由于解释器在运行时之前不知道类可能具有哪些属性,如果该属性是变量、方法等,则需要在运行时使用绑定到类的某种容器。在其他语言中,如C++,这是通过使用函数指针数组(通常是不保证的)或虚拟表来实现的,允许您动态地将预定义的方法集更改为类。但是,由于方法名已经硬编码,因此不允许动态地向类中添加或删除方法。除了hashmap或二进制搜索树之外的任何方法都可能无法有效地允许动态类型。你知道吗tldr公司
基本上,是的。最好不要这样做。使用
__slots__
来最小化类的大小。你知道吗相关问题 更多 >
编程相关推荐