Новые экземпляры локальной функции создаются каждый раз, когда вызывающая функция называется? [Дубликат]

В MySQL есть два типа кавычек:

  1. ' для включения строковых литералов
  2. ` для включения идентификаторов, таких как имена таблиц и столбцов

И тогда есть ", который является частным случаем. Он может быть использован для one вышеупомянутых целей за раз в зависимости от сервера MySQL sql_mode :

  1. By по умолчанию символ " может использоваться для вложения строковых литералов точно так же, как '
  2. В режиме ANSI_QUOTES символ " может использоваться для заключите идентификаторы так же, как `

Следующий запрос приведет к различным результатам (или ошибкам) ​​в зависимости от режима SQL:

SELECT "column" FROM table WHERE foo = "bar"

ANSI_QUOTES disabled

Запрос будет выбирать строковый литерал "column", где column foo равен строке "bar"

ANSI_QUOTES enabled

В запросе будет выбран столбец column где столбец foo равен столбцу bar

. Когда использовать

  • , я предлагаю вам избегать использования ", чтобы ваш код не зависел от SQL mode
  • Всегда указывайте идентификаторы, так как это хорошая практика (довольно много вопросов о SO обсуждают это)

25
задан Aditya 24 December 2013 в 20:09
поделиться

6 ответов

id объекта гарантированно будет уникальным во время жизни этого объекта , а не на протяжении всего времени жизни программы. Два созданных вами объекта someClass существуют только в течение времени вызова print - после этого они доступны для сбора мусора (и в CPython немедленно освобождаются). Поскольку их время жизни не перекрывается, для них действительно существует общий идентификатор.

В этом случае он также невосстанавливается из-за комбинации двух деталей реализации CPython: во-первых, сбор мусора путем подсчета ссылок (с некоторой дополнительной магией, чтобы избежать проблем с циклическими ссылками), а во-вторых, объект id объекта связан со значением базового указателя для переменной (т. е. местоположения ее памяти). Итак, первый объект, который был последним выделенным объектом, сразу освобождается - не удивительно, что выделенный [ следующий объект будет находиться в одном и том же месте (хотя это потенциально также зависит от сведения о том, как был скомпонован переводчик).

Если вы полагаетесь на несколько объектов, имеющих разные id s, вы можете держать их вокруг - скажем, в списке, чтобы их время жизни перекрывалось. В противном случае вы можете реализовать идентификатор класса, который имеет разные гарантии - например:

class SomeClass:
    next_id = 0

    def __init__(self):
         self.id = SomeClass.nextid
         SomeClass.nextid += 1
29
ответ дан lvc 3 September 2018 в 13:07
поделиться

Если вы прочитали документацию для id , в ней говорится:

Вернуть «идентификатор» объекта. Это целое число, которое гарантировано будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимися временами жизни могут иметь одинаковое значение id().

И это именно то, что происходит: у вас есть два объекта с неперекрывающимися сроками службы, потому что первый из них уже вышел


Но не верьте, что это будет всегда . Особенно, если вам нужно иметь дело с другими реализациями Python или с более сложными классами. Все, что говорит язык, состоит в том, что эти два объекта могут иметь одинаковое значение id(), а не то, что они будут . И тот факт, что они делают , зависит от двух деталей реализации:

  • Сборщик мусора должен очистить первый объект, прежде чем ваш код даже начнет выделять второй объект- который, как гарантируется, произойдет с CPython или любой другой реализацией пересчета (когда нет круговых ссылок), но довольно маловероятен с коллективным сборщиком мусора, как в Jython или IronPython.
  • Распределитель под крышками имеет чтобы иметь очень сильное предпочтение повторного использования недавно освобожденных объектов того же типа. Это справедливо в CPython, который имеет несколько уровней фантастических распределителей поверх базового C malloc, но большинство других реализаций намного больше уходят в основную виртуальную машину.

Последнее: факт, что object.__repr__ имеет подстроку, которая оказывается такой же, как id как шестнадцатеричное число, является всего лишь артефактом реализации CPython, который нигде не гарантируется. Согласно docs :

Если это вообще возможно, это должно выглядеть как действительное выражение Python, которое может быть использовано для воссоздания объекта с тем же значением (с учетом соответствующая среда). Если это невозможно, должна быть возвращена строка формы <...some useful description…>.

Тот факт, что CPython object, кажется, помещает hex(id(self)) (фактически, я считаю, что он делает эквивалент sprintf, указав его указатель на %p, но поскольку CPython id просто возвращает тот же самый указатель, который был добавлен к long, который заканчивается тем же самым) нигде не гарантируется. Даже если это было верно, так как ... до object даже существовало в начале 2.x дней. Вы можете полагаться на него для такого простого простого «что здесь происходит» отладки в интерактивном приглашении, но не пытайтесь использовать его за его пределами.

13
ответ дан abarnert 3 September 2018 в 13:07
поделиться

Пример, когда место памяти (и id) не освобождено:

print([someClass() for i in range(10)])

Теперь идентификаторы уникальны.

0
ответ дан hpaulj 3 September 2018 в 13:07
поделиться

Он освобождает первый экземпляр, поскольку он не был сохранен, тогда, поскольку между тем ничего не случилось с памятью, он создает второй раз в том же месте.

3
ответ дан mhlester 3 September 2018 в 13:07
поделиться

Я чувствую здесь более глубокую проблему. Вы не должны полагаться на id, чтобы отслеживать уникальные экземпляры на протяжении всей вашей программы. Вы должны просто увидеть его как не гарантированный индикатор местоположения памяти в течение всего экземпляра объекта. Если вы сразу создаете и освобождаете экземпляры, вы можете очень хорошо создавать последовательные экземпляры в том же месте памяти.

Возможно, вам нужно отслеживать статический счетчик класса, который присваивает каждому новому экземпляру уникальный идентификатор, и увеличивает статический счетчик класса для следующего экземпляра.

4
ответ дан Preet Kukreti 3 September 2018 в 13:07
поделиться

Попробуйте это, попробуйте вызвать следующее:

a = someClass()
for i in range(0,44):
    print(someClass())
print(a)

Вы увидите что-то другое. Зачем? Причина того, что память, выпущенная первым объектом в цикле «foo», была повторно использована. С другой стороны, a не используется повторно, поскольку сохраняется.

3
ответ дан Willem Van Onsem 3 September 2018 в 13:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: