2017-02-01 6 views
2

Я хочу сделать свой код более (память-) эффективным. Сейчас у нас есть много функций, которые принимают итератор в качестве параметра, как:Является ли пустой кортеж в Python «постоянным»

def foo(para,meter,iterable): 
    #... 
    pass 

и иногда мы должны предоставить ему пустой список, чтобы сделать свою работу должным образом: foo(14,25,[]). Проблема заключается в том, что каждый раз, когда создается новый список: он должен выделяться в куче, а список кажется 64 байтам памяти (на моей собственной машине, проверен с sys.getsizeof([])), тогда как пустой кортеж только берет (потенциально один время) 48 байт.

Я поэтому задавался вопросом, является ли пустой кортеж константой. Поскольку кортежи неизменяемы, можно легко сделать кортеж с длиной 0 (так ()) константой в программе. Это уменьшило бы «время строительства» (ну нет, поскольку он только установил ссылку на константу) и уменьшил объем выделенной памяти.

Вопрос в том, есть ли гарантии относительно интерпретатора Python (то есть любого популярного интерпретатора), что пустой кортеж действительно является константой, так что () не требует времени строительства и не выделяет дополнительную память.

Тестирование его id(..), кажется, поддерживает теорию, что есть на самом деле только один нуль-кортеж:

>>> id(()) 
140290183798856 
>>> a =() 
>>> id(a) 
140290183798856 

, но это может быть возможно, что во время выполнения в Python интерпретатор вилы кортежа по какой-то причине.

+0

http://stackoverflow.com/q/38328857/2301450 – vaultah

+0

@vaultah: вопрос был не почему. Я думаю, что вопрос ясно показывает, что у меня есть идея, как он работает за шторами. Вопрос в том, всегда ли ** **, что '() is()'. –

+0

Я думаю, что ответ Джима охватывает это тоже? – vaultah

ответ

8

В CPython пустой кортеж является одноэлементным. Только один экземпляр создается, когда-либо, а затем повторно используется всякий раз, когда вы используете () или используете tuple() на пустом генераторе.

PyTuple_new() function по существу делает это:

if (size == 0 && free_list[0]) { 
    op = free_list[0]; 
    Py_INCREF(op); 
    // ... 
    return (PyObject *) op; 
} 

Таким образом, если размер кортежа 0 (пусто) и free_list[0] объект существует (существующий пустой кортеж синглтон), просто использовать.

См. How is tuple implemented in CPython? для получения более подробной информации о free_list; CPython также будет повторно использовать уже созданные tuple экземпляры до длины 20.

Это деталь реализации. Другие реализации (Jython, IronPython, PyPy) не должны делать то же самое.

Смежные вопросы