Изменить базовые (неизменяемые) типы внутри функции в Python?

Я использую C++ SDK, где есть такая функция (у нее есть оболочка python, но не документы):

getPos ( int uvId, float & u, float & v ) const 

Как мне указать в Python, чтобы переданные переменные были изменены?

Я попробовал этот пример, чтобы увидеть, могу ли я изменить числа с плавающей запятой внутри функции, но это не сработало, поэтому я напечатал 12.0:

def change ( a ) :

    a = 35.0


b = 12.0

change ( b )

print b

Итак, как мне вызвать эту функцию, чтобы я мог изменить 2 внешних поплавка в Python?

Связанный:


person Joan Venge    schedule 23.02.2009    source источник
comment
Я добавил ссылку на связанный вопрос   -  person jfs    schedule 24.02.2009
comment
Посмотрите, как обрабатывается аргумент для функции Operation(): stackoverflow.com/questions/540427/   -  person jfs    schedule 24.02.2009
comment
@Joan Venge: базовые типы не имеют никакого значения в Python. Я думаю, вы говорите о неизменяемых типах. Или вы можете говорить о типах языка C. Возможно, вы захотите обновить свой вопрос.   -  person S.Lott    schedule 24.02.2009
comment
Спасибо, я думал, что в питоне они тоже называются базовыми типами. Итак, все строки, целые числа, числа с плавающей запятой неизменяемы?   -  person Joan Venge    schedule 24.02.2009
comment
Как и кортежи. Вероятно, несколько других вещей. Но то, что является примитивным в Java и C++, является (как правило) неизменяемым объектом в Python, поэтому они похожи на другие языки.   -  person S.Lott    schedule 24.02.2009


Ответы (4)


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

Инструмент (или человек), сгенерировавший оболочку Python для функции C++, должен был сделать что-то особенное для поддержки этой функции (надеюсь, иначе вы не сможете ее использовать). Знаете ли вы, какой инструмент использовался для создания оболочки?

Обычно подобные инструменты генерируют некий тип данных контейнера:

b.value = 12.0
change(b)
print b.value
person Tom Lokhorst    schedule 23.02.2009
comment
Спасибо, они использовали Swig, но я не знаю, как они могли это сделать, не меняя тип возвращаемого значения. - person Joan Venge; 24.02.2009
comment
Справедливости ради, все (как бы) вызывается по ссылке, просто числа неизменяемы. Таким образом, вы не меняете атрибуты объекта, привязанного к имени a в функции, а перепривязываете a к совершенно другому объекту. - person Mike Boers; 24.02.2009
comment
Спасибо, Майк, это то, о чем я думал. - person Joan Venge; 25.02.2009
comment
Я не эксперт в Python, но думаю, что все передается по значению (копированием). Просто, поскольку все является объектом, то, что копируется, всегда является ссылкой (да, это звучит запутанно). - person Tom Lokhorst; 25.02.2009
comment
Итак, у вас всегда есть копии ссылки на какой-то объект. Однако некоторые объекты (например, списки) можно изменить, а другие (например, числа или кортежи) нельзя изменить, они неизменяемы. - person Tom Lokhorst; 25.02.2009

В Питоне:

def getPos(uvID):
    # compute u, v
    return u, v

# 
u, v = getPos(uvID)
person jfs    schedule 23.02.2009
comment
+1: несколько возвращаемых значений - обычно это основное значение кода C/C++. - person S.Lott; 24.02.2009
comment
Спасибо, ребята, но в приведенном выше случае с функцией getUV они этого не сделали, хотелось бы, но нет. - person Joan Venge; 24.02.2009
comment
В этом случае вам придется написать свой собственный API, чтобы сделать этот фрагмент C++ совместимым с Python. - person S.Lott; 24.02.2009
comment
Спасибо, я бы хотел, но это стороннее программное обеспечение. Не могу поверить, что они упустили это из виду. - person Joan Venge; 24.02.2009

Вам придется прибегнуть к ctypes.

В частности, см. https://docs.python.org/library/ctypes.html#passing-pointers-or-passing-parameters-by-reference

person S.Lott    schedule 24.02.2009

Для простых случаев функция возвращает новое значение.

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

def foobar(alist):
    alist[0] = 10

blist = [42]
foobar(blist)
print blist[0]

Редактировать:

Для переноса ссылок на С++ не существует стандартного способа (базовые интерфейсы python находятся на уровне C, а не на С++), поэтому это зависит от того, как был реализован интерфейс python - это могут быть массивы или возврат нескольких значений. Я не уверен, как это обрабатывает boost.python, но вы можете начать с него или, может быть, посмотреть под отладчиком, чтобы увидеть, как обрабатывается параметр.

person Douglas Leeder    schedule 23.02.2009
comment
Спасибо, но функция getPos и ​​многое другое — это C++, и я не могу их изменить. Все завернуто в Python, поэтому я предполагаю, что должен быть способ его использовать. - person Joan Venge; 24.02.2009