Function args

  • Thread starter Jean-Michel Caricand
  • Start date
J

Jean-Michel Caricand

Hi,

I'm new in Python. I have a problem with function args. I want to pass
args by reference because the function must modify this arg. How I do
that in Python.

I didn't found documentation !
 
M

Michel Claveau/Hamster

Bonjour !

En Python, les variables sont des sortes de pointeurs sur des objets. Tout
passage de variable comme paramètres se fait forcément par référence (en
fait, on passe la référence à l'objet).
De plus l'affectation d'une variable crée un autre objet, car la plupart des
objets ne sont pas modifiables.

Seuls le sont les listes et les dictionnaires sont modifiables. Une chaîne
de caractères n'est pas modifiable non plus.

Cependant, il existe des modules contenant d'autres types ayant des
comportement différents. Il est également possible de définir ses propres
classes, dont on (re)-définira le comportement.



PS : il existe aussi un newsgroup fr.comp.lang.python



@-salutations
 
J

Jean-Michel Caricand

Bonjour Michel et merçi pour la réponse très rapide. Je tiens à préciser que
nous développons en interne
en langage Perl. Ma question peut donc sembler bête pour des programmeurs
Python.

Après maintes recherches, je n'ai pas trouvé d'exemples me permettant de
comprendre le mécanisme employé
par Python pour passer un simple nombre à une fonction et le modifier
réellement.

Imaginons que je veuille écrire une fonction qui permute deux variables,
j'écris :

def permuter(a,b):
c = b
b = a
a = c

Si tout est objet, donc passé par référence a et b devraient être réellement
modifier ? Pourtant ce n'est pas le cas.

Pourriez simplement me donner un exemple pour cette fonction. Encore merçi
 
M

Michel Claveau/Hamster

Re

Je redis : en Python, les objets ne sont pas modifiables (sauf listes et
dictionnaires).

En faisant :
c = b
b = a
a = c

Cela veut dire :
- c=b création d'un objet auquel on affecte la valeur b, avec une variable
c qui pointe dessus
- b=a création d'un objet auquel on affecte la valeur a, avec une variable
b qui pointe dessus
- a=c création d'un objet auquel on affecte la valeur c, avec une variable
a qui pointe dessus

Donc, au résultat, on aura bien eu un échange des valeurs, mais avec
création d'objets.

D'ailleurs, on peut suivre ce qui se passe, avec id() qui donne
l'identifiant unique d'un objet.

a=2
print id (a)
a=3
print id(a)
a+=1
print id(a)

On voit bien qu'il y a création d'un nouvel objet 'a' à chaque affectation.

Il faut comprendre qu'il y a deux notions :
- en Python, une variable est toujours une référence (à un objet)
- les objets ne sont pas modifiables (sauf listes et dictionnaires)




Si tu veux vraiment utiliser des objets modifiables, passe par une liste, ou
un dictionnaire.
Exemple avec un dictionnaire :
def permut(x,y):
d[x],d[y]=d[y],d[x]

d={'a':2, 'b':3}
print d['a'],d['b']
print id(d['a']),id(d['b'])

permut('a','b')
print d['a'],d['b']
print id(d['a']),id(d['b'])


On voit bien, ici, grâce a "id()", qu'ici, il y a eu échange des adresses
(référence) des éléments internes du dictionnaire.


Ce système de gestion des objets par référence, dans Python, est assez
fabuleux, car une variable peut référencer n'importe quel objet : un nombre,
une fonction, un dictionnaire, une liste de liste de liste, une classe, etc.
Les possibilités deviennent inouïes. Mais il faut bien maîtriser les notions
d'abord.



@-salutations

Michel Claveau
 
M

Michel Claveau/Hamster

Re-re

Il y a bien un moyen, mais assez tordu.

La fonction globals() permet de connaître toutes les références d'objet,
mais aussi de les manipuler.

Exemple :

a,b=2,3
print a,b # => 2,3
print id(a),id(b)

globals()['a']=globals()['b']

print a,b # => 3,3
print id(a),id(b) # a et b pointent sur le même objet !!!



Avec cette technique, la ligne suivante :

globals()['a'],globals()['b']=globals()['b'],globals()['a']

échangera les références de 'a' et de 'b', sans toucher aux objets
eux-mêmes.



Mais a-t'on vraiment besoin de ce genre de chose ?
 
Y

Yermat

Jean-Michel Caricand said:
Bonjour Michel et merçi pour la réponse très rapide. Je tiens à préciser que
nous développons en interne
en langage Perl. Ma question peut donc sembler bête pour des programmeurs
Python.

Après maintes recherches, je n'ai pas trouvé d'exemples me permettant de
comprendre le mécanisme employé
par Python pour passer un simple nombre à une fonction et le modifier
réellement.

Imaginons que je veuille écrire une fonction qui permute deux variables,
j'écris :

def permuter(a,b):
c = b
b = a
a = c

Si tout est objet, donc passé par référence a et b devraient être réellement
modifier ? Pourtant ce n'est pas le cas.

[...]

En plus "permuter" est un mauvais exemple psuique l'on peut faire :2 1

En gros, tous les types primitifs de python sont "expansés", autrement
dit quand on les affecte à une autre variable, c'est une copie.
Tous les types complexes sont des références.

Yermat
 
P

Peter Otten

Jean-Michel Caricand said:
Imaginons que je veuille écrire une fonction qui permute deux variables,
j'écris :

def permuter(a,b):
c = b
b = a
a = c

Si tout est objet, donc passé par référence a et b devraient être
réellement modifier ? Pourtant ce n'est pas le cas.

Assignments inside a function only affect local bindings, i. e what a and b
"point" to in the local context. Rebinding in the calling context must be
made explicit:
1

Of course you wouldn't write a function for that particular example:

Does the above mean you can never change an object from inside a function?
No, only bindings cannot be changed and because integers are "immutable",
i. e. cannot be changed once they are created, what is viewed as changing
them is in fact rebinding. Now a simple example with a mutable class:
.... def __init__(self, name, value):
.... self.name = name
.... self.value = value
.... def __repr__(self):
.... return "A(name=%r, value=%r)" % (self.name, self.value)
........ a.value, b.value = b.value, a.value
....(A(name='A', value=2), A(name='B', value=1))

While objects stay the same, you can do anything with the attributes. As
Michel Claveau already pointed out, the same is true for list and dict
items.

Peter
 
M

Michel Claveau/Hamster

Bonjour !
dit quand on les affecte à une autre variable, c'est une copie. Tous les
types complexes sont des références.

Je comprend, mais, dans mon esprit, je préfère me dire qu'il y a copie de ce
qui est pointé. Pour une variable simple (e.g. a=2) c'est l'objet '2' qui
est pointé, et donc, copié. Dans le cas d'une liste, la liste pointe sur un
ensemble de pointeurs vers différents objets, et donc, on copie ces
pointeurs (qui sont pointés).

Malheureusement, mon point de vue accroche sur les tuples (non modifiables).
Je me dis alors que les tuples sont non modifiables par exception...


Cela revient un peu au même que ce que tu as exprimé, avec une image mentale
un peu différente.


@-salutations
 
Y

Yermat

Michel said:
Bonjour !



dit quand on les affecte à une autre variable, c'est une copie. Tous les
types complexes sont des références.

Je comprend, mais, dans mon esprit, je préfère me dire qu'il y a copie de ce
qui est pointé. Pour une variable simple (e.g. a=2) c'est l'objet '2' qui
est pointé, et donc, copié. Dans le cas d'une liste, la liste pointe sur un
ensemble de pointeurs vers différents objets, et donc, on copie ces
pointeurs (qui sont pointés).

Malheureusement, mon point de vue accroche sur les tuples (non modifiables).
Je me dis alors que les tuples sont non modifiables par exception...


Cela revient un peu au même que ce que tu as exprimé, avec une image mentale
un peu différente.


@-salutations

Oui je comprends bien mais si j'ai bien compris votre représentation que
devrait faire ceci :
>>> l = ['a','b','c']
>>>
>>> d = l
>>> d.append('d')
>>> d
['a', 'b', 'c', 'd']

Que devrait valoir l maintenant ? Python fait :['a', 'b', 'c', 'd']

votre représentation ferait :
['a','b','c']

Mais bon. L'important est d'avoir compris ;-)

Yermat
 
F

Fraser Hanson

Jean-Michel Caricand said:
Hi,

I'm new in Python. I have a problem with function args. I want to pass
args by reference because the function must modify this arg. How I do
that in Python.

I didn't found documentation !

The short answer is, you can modify mutable types(lists and
dictionaries) by passing them to a function. You cannot modify
immutable types (strings, numbers, tuples) in this way. If you want to
modify a variable pointing to an immutable type, then you must have your
function return the modified value or values, and assign your value to
the result of your function. Like this:

def func(s):
return s + " shop"

a = "cheese"
a = func(a)
print a # prints "cheese shop"

Python allows you to return multiple variables from a function call, so
you can modify any number of variables with this method. (Technically,
when you use a statement like "return a,b,c" you are not returning three
variables, you are returning one tuple. Still it looks and acts like
three variables, it's just good to be aware of these things.)

def func(x,y,z):
x = x + 5
y = y + 10
z = z + 15
return x, y, z

a, b, c = 1, 2, 3
a, b, c = func(a,b,c)
print a, b, c # prints "6, 12, 18"


The reason for this is as follows.

All variables in Python are just names that point to the "real" object,
sort of like C pointers. When you pass an immutable type argument to a
function, the function receives a new variable that happens to be
pointing to the same object. When you assign to that variable, you are
making it point to a different object. Thus when your function exits,
your old variable in the original scope still points to the same object
it did before the function call. By assigning the original variable to
something returned by your function, your are achieving the intended
effect in a more explicit way.

Some of this is discussed in the documentation here:

Mutable and immutable types:
http://www.python.org/doc/2.3.3/ref/objects.html

What happens during assignment:
http://www.python.org/doc/2.3.3/ref/assignment.html

--Fraser Hanson

ps. Are you aware that your message was posted 12 times in a row?
 
E

Elaine Jackson

I see from further on in the discussion that you've got the picture, so I'll
just add a couple of things that may be useful for you to know:

The keyword 'is' compares actual identity instead of just equality. (In other
words, 'a is b' returns the same value as 'id(a)==id(b)')
The function call 'globals()' returns a dictionary representing the current
global namespace.

| Bonjour Michel et merçi pour la réponse très rapide. Je tiens à préciser que
| nous développons en interne
| en langage Perl. Ma question peut donc sembler bête pour des programmeurs
| Python.
|
| Après maintes recherches, je n'ai pas trouvé d'exemples me permettant de
| comprendre le mécanisme employé
| par Python pour passer un simple nombre à une fonction et le modifier
| réellement.
|
| Imaginons que je veuille écrire une fonction qui permute deux variables,
| j'écris :
|
| def permuter(a,b):
| c = b
| b = a
| a = c
|
| Si tout est objet, donc passé par référence a et b devraient être réellement
| modifier ? Pourtant ce n'est pas le cas.
|
| Pourriez simplement me donner un exemple pour cette fonction. Encore merçi
|
| "Michel Claveau/Hamster" <[email protected]> a écrit
| dans le message de [email protected]...
| > Bonjour !
| >
| > En Python, les variables sont des sortes de pointeurs sur des objets. Tout
| > passage de variable comme paramètres se fait forcément par référence (en
| > fait, on passe la référence à l'objet).
| > De plus l'affectation d'une variable crée un autre objet, car la plupart
| des
| > objets ne sont pas modifiables.
| >
| > Seuls le sont les listes et les dictionnaires sont modifiables. Une chaîne
| > de caractères n'est pas modifiable non plus.
| >
| > Cependant, il existe des modules contenant d'autres types ayant des
| > comportement différents. Il est également possible de définir ses propres
| > classes, dont on (re)-définira le comportement.
| >
| >
| >
| > PS : il existe aussi un newsgroup fr.comp.lang.python
| >
| >
| >
| > @-salutations
| > --
| > Michel Claveau
| > mél : http://cerbermail.com/?6J1TthIa8B
| > site : http://mclaveau.com
| >
| >
|
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,181
Messages
2,570,970
Members
47,537
Latest member
BellCorone

Latest Threads

Top