
Здравствуйте, постараюсь максимально подробно описать суть проблемы:
Почти год программирую на Python 3, потребовалось использовать указатель на переменную, которая может являться как изменяемой (mutable), например list
, так и неизменяемой (immutable), например float
.
Требуется используя адрес переменной «A» записать адрес в переменную «B», таким образом, чтобы после изменения «A», через переменную «B» можно было узнать значение в «A».
Пример на С/C++:
int A=0; int *B; B=&A; printf("%d\n", *B); //ответ: 0 A=1; printf("%d\n", *B); //ответ: 1
Пытаюсь реализовать на Python и написать функцию, которая принимает два элемента, например «element» и «under_element», где «element» типа список (list), «under_element» любой объект (float
, str
, list
, «мой_объект»).
Функция записывает адрес объекта «under_element», в один из элементов списка «element» так, что при изменении «under_element» используя объект «element» можно было бы узнать актуальное значение «under_element»
Пример структуры функции на Python 3 («укороченный»):
def f(element, under_element, i=0): print("depth=", i, "\tfs_element=", element) if(i<1): f(element[0], under_element, i+1) else: element=under_element print("depth=", i, "\tff_element=", element) element=[[0],[1]] under_element='str' print("start_element=", element, "\n") f(element, under_element) under_element='list' print("\nfinish_element=", element)
Результат работы программы:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= str depth= 0 ff_element= [[0], [1]] finish_element= [[0], [1]]
Желаемый результат работы программы:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= str depth= 0 ff_element= ['str', [1]] finish_element= ['list', [1]]
Нашел решение состоящее из четырех пунктов:
- все элементы заключать в
list
, пример:under_element=['str']
- передавать в функцию переменные в виде лист
- обращаться к записываемому объекту без дополнительных
[]
(без указания глубины) - обращаться к объекту, в который записываем с дополнительным
[]
(с указанием глубины)
Пример переделанной функции:
def f(element, under_element, i=0): print("depth=", i, "\tfs_element=", element) if(i<1): f(element[0], under_element, i+1) else: element[0]=under_element print("depth=", i, "\tff_element=", element) element=[[0],[1]] under_element=['str'] print("start_element=", element, "\n") f(element, under_element) under_element[0]='list' print("\nfinish_element=", element)
Результат работы программы:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= [['str']] depth= 0 ff_element= [[['str']], [1]] finish_element= [[['list']], [1]]
Недостатки данного решения:
- мусор в массивах и коде программы
- нет гарантии, что пользователь функции пользуется переменными, как указано выше к данному примеру, и не передаст объект являющийся immutable (
float
,str
и др.)
Повторюсь:
Требуется обратиться к объекту (1) через другой объект (2), например через элемент списка, или чтобы значение объекта (1) было в объект (2), даже после изменения объекта (1), другими словами всегда соответствовало значению объекта(1)
Пример:
A=0
запоминаем адрес в «B»
А=1
смотрим на «А» через «B» получаем 1
(после записи адреса «A» в «B», нельзя обратиться к «A», но требуется взять значение «А», которое в нее записано)
3Answers

Еще может заинтересовать:

Требуется используя адрес переменной «A» записать адрес в переменную «B», таким образом, чтобы после изменения «A», через переменную «B» можно было узнать значение в «A».
Не стоит пытаться использовать синтаксис Питона, чтобы писать на каком-то другом языке. Даже если вам удастся выразить чужие понятия, это скорее всего приведёт к неидиоматичному коду (сложному для понимания и неэффективному).
Программируя на Питоне, старайтесь мыслить в терминах Питона. В Питоне есть имена и объекты. Контейнеры содержат ссылки на другие объекты. Никаких указателей нет. Data model.
Пример на С/C++:
<code>int A=0; int *B; B=&A; printf("%dn", *B); //ответ: 0 A=1; printf("%dn", *B); //ответ: 1</code>
В Питоне целые числа неизменяемы. К примеру, вы не можете поменять значение объекта, который представляет ноль. Присваивание целых (int) в ПитонеA = 1
в Питоне не кладёт 1
в коробку с адресом A
. В Питоне, A = 1
говорит, что к объекту 1
можно по имени A
обращаться (ярлык прилепили): Python has «names» (на картинки посмотрите).
Задача записать в список элемент так, чтобы последующие изменения этого элемента можно было увидеть через элемент списка, в который я его записал. Теоретически это поможет оптимизировать код, т.к. мне не придется искать элементы, которые я записал, проверяя все элементы в списке, т.к. я смогу сразу обращаться к нему, количество элементов произвольное количество и зависит от предустановок
Вот здесь мы к действительной проблеме приближаемся. У вас есть некоторый алгоритм, который становится неэффективным, если его механически из Си на Питон перенести. То есть это XY-задача. Вместо попыток буквального переноса Си решения, стоит рассмотреть исходную задачу (которую Си код призван был решить) и выбрать более подходящее для Питона решение — не оглядываясь на реализации в Си. То есть необходимо привести изначальную задачу, которую вы пытались решить с помощью поиска элементов.

Слегка модифицированный первый пример:
def f(element, under_element, i=0): print("depth=", i, "\tfs_element=", element) if(i<1): element[0] = f(element[0], under_element, i+1) else: element = under_element print("depth=", i, "\tff_element=", element) return element element=[[0],[1]] under_element='str' print("start_element=", element, "\n") f(element, under_element) under_element='list' print("\nfinish_element=", element)
Дает такой результат:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= str depth= 0 ff_element= ['str', [1]] finish_element= ['str', [1]]
Вот это:
under_element='str' f(element, under_element) under_element='list' # хотим, чтобы 'str' внутри списка заменилось на 'list'
не сработает, потому что в функцию передается не указатель на переменную under_element
(чего можно было бы добиться в Си), а значение переменной. В Python передать ссылку (или указатель) на переменную внутрь функции нет никакой возможности. Если очень захотеть, можно передать имя переменной, а потом по этому имени обратиться к глобальной переменной, но я не советовал бы так делать.
Как вариант, можно использовать «контейнерный» класс, в котором уже будет храниться значение, которое вы хотите изменять:
class Container: def __init__(self, item): self.item = item def __repr__(self): return 'Container(%r)' % self.item def __str__(self): return str(self.item) def f(element, under_element, i=0): print("depth=", i, "\tfs_element=", element) if(i<1): element[0] = f(element[0], under_element, i+1) else: element = under_element print("depth=", i, "\tff_element=", element) return element element=[[0],[1]] under_element=Container('str') print("start_element=", element, "\n") f(element, under_element) under_element.item='list' print("\nfinish_element=", element)
Вывод:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= str depth= 0 ff_element= [Container('str'), [1]] finish_element= [Container('list'), [1]]
Если поменять реализацию метода __repr__
в классе Container
:
class Container: def __init__(self, item): self.item = item def __repr__(self): return repr(self.item) def __str__(self): return str(self.item)
то формально вывод будет совпадать с требуемым:
start_element= [[0], [1]] depth= 0 fs_element= [[0], [1]] depth= 1 fs_element= [0] depth= 1 ff_element= str depth= 0 ff_element= ['str', [1]] finish_element= ['list', [1]]
Но это не значит, что в списке хранится строка, просто класс при преобразовании в строку (например при выводе через print
) будет «притворяться» строкой (точнее даже тем значением, которое лежит в поле .item
, независимо от его типа). Но строковые операции с этим классом (сцепление со строкой и т.д.) не будут работать, нужно будет явно обращаться к полю .item
объекта.
Еще добавлю — это все по сути попытка подтянуть низкоуровневые особенности С/С++ к Python, что изначально неправильно. Нужно исходить наоборот от реальной задачи, потом переходить к абстрактным типам данных (графы, деревья и т.д.), которые в разных языках реализуются по-разному, и дальше уже реализовывать способом идиоматичным для выбранного языка.

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