Ссылки и контекст через функции и классы

Сначала просто хочу сказать, что я новичок в python и использую python версии 3.6.5. Я не очень-то согласен с тем, как Python обрабатывает ввод функции как «ссылки на объекты».

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

Это первый код, который я запускаю (неправильное поведение):

integer = 0

def func(t): return integer

class FooClass(object):
    def __init__(self, input_function):
        self.function = input_function

    def give_value(self, index):
        print(self.function(index))

foo_object = FooClass(func)

foo_object.give_value(0)
# Output >> 0

integer = 1

foo_object.give_value(0)
# Output >> 1

Я хочу, чтобы мой объект FooClass был полностью независим от внешних изменений.

Это второй код, который я запускаю (правильное поведение):

integer = 0

def step_function(integer_input):   
    def func(t): return integer_input

    return FooClass(func)

class FooClass(object):
    def __init__(self, input_function):
        self.function = input_function

    def give_value(self, index):
        print(self.function(index))

foo_object = step_function(integer)

foo_object.give_value(0)
# Output >> 0

integer = 1

foo_object.give_value(0)
# Output >> 0

Я доволен этим, но не понимаю, почему это работает. На самом деле, я боюсь, что моя функция self.function относится к 'integer_input', определенному во время вызова step_function. Так что это относится к доступному пространству памяти, которое можно переопределить (если это имеет смысл в Python).

Заранее спасибо!

Мне чрезвычайно сложно понять ваш код, потому что все имена переменных представляют собой бессмысленные буквы (отредактируйте: некоторые из которых вы повторное использование!). Кроме того, не могли бы вы привести более короткий пример, демонстрирующий то же поведение, которое вас раздражает? А пока у меня есть подозрение, что это вам поможет в любом случае.

timgeb 02.05.2018 16:36

@timgeb Хорошо, спасибо, я отредактирую вопрос, чтобы было легче понять. Я вернусь после просмотра видео.

LA. Dufrene 02.05.2018 16:43

Если вы переходите с другого языка, может быть сложно привыкнуть к модели данных Python. Вы можете найти эту статью полезной: Факты и мифы об именах и ценностях Python, написанную ветераном SO Недом Батчелдером. Более короткий и несколько иной взгляд на эту тему см. В В других языках есть «переменные», в Python - «имена»..

PM 2Ring 02.05.2018 16:52
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, чтобы объяснить, почему ваши коды работают по-другому: integer - это имя, которое относится к целому числу. В вашем первом примере вы используете это имя в func, и это создает замыкание, которое включает ссылку на integer из области Глобальный и передает ее. Таким образом, все будущие вызовы ссылаются на то, что содержится под именем integer в глобальной области видимости.

Во втором примере вы создаете новое имя integer_input для ссылки на integer и ссылки на integer_input в func. Это создает замыкание, которое оборачивает ссылку на integer_input из области функция и передает ее.

Если бы вы каким-то образом смогли изменить то, на что ссылается integer_input в вашем прицеле step_function, вы столкнулись бы с той же проблемой, но это было бы трудно сделать (и практически невозможно сделать непреднамеренно).

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

func = (lambda value: lambda t: value)(integer)

Это вручную создает замыкание для отделения названиеinteger от объект, на которое ссылается integer, и аналогично вашему второму примеру.

Или, чтобы обновить вашу текущую структуру, чтобы сделать что-то подобное:

def step_function(integer_input):   
    def inner(t): return integer_input
    return inner

func = step_function(integer)

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

Спасибо! Я отредактировал код с помощью более простого примера, поэтому я не знаю, следует ли мне отменить редактирование или вы можете адаптировать свой ответ к новому коду. Если я понимаю ваш ответ, переменная bar остается в области действия функции, но эта область все еще существует после вызова foo?

LA. Dufrene 02.05.2018 17:28

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

LA. Dufrene 02.05.2018 17:39

@ LA.Dufrene Да, область видимости все еще существует после return FooClass(func), потому что FooClass хранит ссылку на func, а func должен знать значение integer_input, поэтому это заключено в закрытие.

Jared Goguen 02.05.2018 17:55

Спасибо за новый ответ. Я прекрасно понимаю, что сейчас происходит!

LA. Dufrene 02.05.2018 18:08

Другие вопросы по теме