sys.getsizeof
:
>>> import sys
>>> a = 'a' * 999_999
>>> sys.getsizeof(a) # 1 byte per character, plus some overhead
1000048
>>> cry_laugh = '\U0001f602' # cry-laughing emoji
>>> sys.getsizeof(cry_laugh) # mostly overhead
80
>>> sys.getsizeof(a + cry_laugh) # 4 bytes per character, plus some overhead
4000076
Точные детали могут отличаться в зависимости от платформы или версии Python.
Если вы хотите добиться большей эффективности использования пространства в вашем языке, вы можете рассмотреть возможность использования UTF-8 нативно, как это сделали некоторые другие языки.
Преимущество этого метода в том, что оптимизация, которую вы ищете, приходит бесплатно.
Недостаток, и основная причина, по которой CPython использует свой собственный метод, заключается в том, что индексирование больше не является дешевым.
my_string[some_index]
- это O(1) в Python, потому что он может индексировать строки так же, как C индексирует массивы: В псевдокоде, он может читать память по адресу my_string.data_start + some_index * my_string.bytes_per_character
. Это происходит еще с тех времен, когда строки в Python были байтовыми строками, и было написано много кода, который зависит от этой производительности.
Однако UTF-8 не может этого гарантировать, поскольку не все кодовые точки имеют одинаковую длину. Чтобы получить n-ю кодовую точку в строке, закодированной в UTF, необходимо перебрать n кодовых точек, чтобы найти правильное смещение.
Это не обязательно должно быть проблемой, если ваши пользователи ожидают такого поведения. Это просто означает, что вместо того, чтобы писать код типа:
for i in range(len(my_string)): # un-Pythonic but still fast in CPython
do_something_with(my_string[i])
вы захотите поощрять пользователей писать такой код:
for code_point in my_string: # fast both in CPython and runtimes using UTF-8
do_something_with(code_point)
Я не рекомендую предоставлять индексный оператор для строк, например, если это будет медленнее, чем O(log(n)).
Прикрепляю к посту несколько видео по теме: