При добавлении в список почему Python копирует значения вместо указателей? - PullRequest
2 голосов
/ 05 января 2012

То, что я пытался сделать (код C):

int a = 2, b = 3, c = 4;

int* arr[3] = {&a, &b, &c};

for (int i = 0; i < 3; ++i) {
    if (*(arr[i]) > 1) {
        *(arr[i]) = 1
    }
}

Я ожидал, что Python будет делать подобное поведение указателя с этим фрагментом кода.

>>> a = 2
>>> b = 3
>>> c = 4
>>> for x in [a, b, c]:
...     if x > 1:
...             x = 1
... 
>>> a,b,c
(2, 3, 4)

Как можнокод на C, как поведение должно быть достигнуто в Python?

Ответы [ 6 ]

6 голосов
/ 05 января 2012

В Python нет указателей в этом смысле.

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

Вы можете достичь чего-то немного похожего на , используя locals:

>>> a = 2
>>> b = 3
>>> c = 4
>>> for x in 'a','b','c':
...    if locals()[x] > 1:
...       locals()[x] = 1
... 
>>> a
1

Однако, Я бы настоятельно рекомендовал не делать этого . Если вы разместите другой вопрос, объясняющий проблему, которую вы пытаетесь решить, вы получите более "Pythonic" способ сделать это.

Это может быть просто случай сохранения ваших значений в dict:

>>> vals = { 'a' : 2, 'b' : '3', 'c' : 4 }
>>> for key,value in vals.items():
...     if value > 1:
...        vals[key] = 1
... 
>>> vals
{'a': 1, 'c': 1, 'b': 1}
3 голосов
/ 05 января 2012

Для этого вы должны использовать изменяемые объекты.
Например:

a = 2
b = 3
c = 4

ls = [a, b, c]

for i, val in enumerate(ls):
     if val > 1:
        ls[i] = 1

print ls

дает вам:

[1, 1, 1]

если вам нужно a, b, c:

>>> [a, b, c] = ls
>>> a
1
2 голосов
/ 05 января 2012

Может быть, это будет полезно

a,b,c  =  [ 1 if i>1 else i for i in [ a, b, c ] ]
a,b,c = map( lambda x: 1 if x>1 else x, [a,b,c] ) #lambda or name of some function
1 голос
/ 05 января 2012

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

Таким образом, с этим в стороне, вы можете отбросить осторожность и управлять переменными по имени:

a, b, c = 2, 3, 4

for name in ['a','b','c']:
    if locals()[name] > 1:
        locals()[name] = 1

print a, b, c
1 голос
/ 05 января 2012

Когда вы делаете x = 5, вы изменяете ссылку, а не базовое значение.Теперь ссылка x указывает на значение 5 (которое обычно представляет собой только один объект в интерпретаторе).

В python вы кодируете по-другому.То, что вы пытаетесь достичь, делается следующим образом:

arr = [2, 3 , 4]
def foo(x):
   return x if x > 1 else x
arr = [foo(a) for a in arr]

Или может быть даже сделано в один лайнер:

>>> [1 if a > 1 else a for a in arr]
[1, 1, 1]
0 голосов
/ 05 января 2012

Как другие ответы вполне объяснили, почему ваши ожидания не могут быть оправданы

Вот одно решение, которое можно добавить в букет

a,b,c = [1 if i > 1 else i for i in [a,b,c]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...