Как переназначить несколько переменных (если возможно) с помощью итератора в Python 3 - PullRequest
0 голосов
/ 03 мая 2020

обновление Добавление примера использования для лучшего объяснения почему Я пытаюсь выявить это поведение. Смотрите обновление в конце поста. Добавлен улучшенный синтаксис для ссылок и добавлена ​​ссылка на статью, предложенную в качестве ответа.

Я пытаюсь использовать итератор для изменения значения списка переменных.

>>> a = 1
>>> b = 2
>>> c = 3
>>> for i in [a,b,c]:
        i += 1
>>> a,b,c #Expecting (2, 3, 4)
(1, 2, 3)

Это не Кажется, не работает, я пробовал другие способы (см. ниже) без успеха. 1. Кто-нибудь, пожалуйста, скажите мне, как лучше подойти к этой проблеме? 2. Кто-нибудь объяснит, почему приведенный выше пример не работает так, как я ожидал? 3. Кто-нибудь скажет мне, как / где я мог найти # 2 в python справочной документации?

Места, которые я ранее искал ответы ...

StackOverflow вопрос «переназначить переменную в исходное значение, определенное до l oop в начале каждого» * ​​1017 *

StackOverflow вопрос о переназначении переменных (но не списка переменных)

Python документы: объекты и типы значений

Python раздел документов 3.1.3

Я чувствую себя как последняя ссылка к python документам можно было бы получить ответ, но я был ошеломлен количеством информации, мой мозг устал, и я надеюсь, что кто-то может помочь.

также пытался ...

>>> help(__name__)
Help on module __main__:

NAME
    __main__

DATA
    __annotations__ = {}
    a = 1
    b = 2
    c = 3
    i = 4

FILE
    (built-in)

но если что, это только смутило меня еще больше.

Наконец я попробовал ...

>>> a = 1
>>> b = 2
>>> c = 3
>>> R = [a, b, c]
>>> for i in range(3):
    R[i] += 1

>>> a, b, c #Hoping for (2, 3, 4)
    (1, 2, 3)
>>> R #Kind of expected (1, 2, 3) based on the above behavior
    [2, 3, 4]

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

>>> x = [a, b, c]

, я создаю список такой, что

x = [the value assigned to a,
 the value assigned to b,
 the value assigned to c]

вместо

x = [переменная a, переменная b, переменная c]

, поэтому, когда я пытаюсь использовать синтаксис

>>> x[0] += 1 #take the current ITEM in place 0 and increment its value by 1.

вместо

>>> a += 1

, это вместо этого интерпретируется как ... принять текущее ЗНАЧЕНИЕ ПУНКТА в месте 0, увеличить это ЗНАЧЕНИЕ на 1, это новое ЗНАЧЕНИЕ ПУНКТА в месте 0 ... , и я теряю ссылку на исходный ПУНКТ .. . переменная a.

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

>>> class breakfast():
>>>     def __init__(self, eggs=None, bacon=None, spam=None):
>>>        self.eggs = eggs
>>>        self.bacon = bacon
>>>        self.spam = spam
>>>        updateOrder = False
>>>        updateItems = []
>>>        for i in [self.eggs, self.bacon, self.spam]:
>>>             if i == None:
>>>                 updateOrder = True
>>>                 updateItems.append(i)
>>>             else:
>>>                 pass
>>>         if updateOrder:
>>>             self.updateOrder(itemsToUpdate = updateItems)
>>>
>>>    def updateOrder(self, itemsToUpdate):
>>>        for i in itemsToUpdate: ###also tried...
>>>     ###for i in range(len(itemsToUpdate)):
>>>            print('You can\'t order None, so I am updating your order to 0 for some of your items.')
>>>            i = 0
>>>         ###itemsToUpdate[i] = 0
>>>
>>> #Finally, the good part, behavior I'm after...
>>> myBreakfast = breakfast(eggs=2,bacon=3)

You can't order None, so I am updating your order to 0 for some of your items.
>>> myBreakfast.spam == 0 #hoping for True....
False

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

>>>     ...
>>>     def updateOrder(self):
>>>         orderUpdated=False
>>>         if self.eggs == None:
>>>             self.eggs = 0
>>>             orderUpdated = True
>>>         if self.bacon == None:
>>>             self.bacon = 0
>>>             orderUpdated = True
>>>         if self.spam == None:
>>>             self.spam = 0
>>>             orderUpdated = True
>>>         if orderUpdated:
>>>             print('You can\'t order None, so I am updating your order')

Однако, если в меню (лотов) больше, чем 3 элемента, код для updateOrder станет очень длинным и хуже повторяется.

1 Ответ

1 голос
/ 03 мая 2020

Вы должны использовать al oop и изменять каждое значение списка в течение l oop

a=[1, 2, 3]
for i in range(len(a)):
    a[i] += 1

Выход будет

[2, 3, 4]

Для доступа и изменения Значения в списке, вам нужно выбрать элементы в зависимости от их местоположения (вы также можете использовать срезы). Итак, a [0] = 1, a [1] = 2 и так далее. Чтобы изменить значение [0], вам нужно присвоить ему новое значение (как это сделано в for l oop).

Ваш пример не работает, потому что вы просто меняете значение i (то есть 1, затем 2, затем 3), вместо фактического изменения списка. Вы не выбираете ни одного элемента из самого списка.

Документация предоставляется здесь (см. Раздел 3.1.3)

РЕДАКТИРОВАТЬ

На основе Ваше пояснение: Создание списка переменных, которые были определены в другом месте:

a, b, c = 5, 6, 7
letters = [a, b, c]

# See id of variable a
id(a) 
# 94619952681856

# See id of letters[0]
id(letters[0]
# 94619952681856

# Add 1 to letters[0]
letters[0] += 1

# See id of letters[0]
# 94619952681888

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

А в примере с завтраком, почему don Вы просто назначаете 0 как значение по умолчанию для каждого di sh вместо None? Это было бы намного проще, если бы не было какой-либо другой причины для этого.

РЕДАКТИРОВАТЬ 2: Если вам нужно обновить ваши атрибуты так, как вы указали, вам нужно будет использовать метод setattr

class breakfast():
    def __init__(self, eggs=None, bacon=None, spam=None):
        self.eggs = eggs
        self.bacon = bacon
        self.spam = spam
        # Create a list of attributes. This will return [self, eggs,bacon,spam]
        attributes = list(locals().keys())
        attributes.remove('self') # Remove self from the list

        updateItems = []
        for i in attributes:
            # Check if the attribute is None or not
            if getattr(self, i) == None:
                updateItems.append(i)
            else:
                pass

        for i in updateItems:
            setattr(self, i, 0) # Set the attributes that are None to 0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...