Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

PyLint et les fonctions lambda

8 réponses
Avatar
Sebastien Aubry
Bonjour,

Je me suis récemment mis à utiliser PyLint pour améliorer la qualité de
mon code Python.
Je trouve ça très bien (cela m'a fait faire beaucoup de progrès), mais
j'ai l'impression qu'il n'aime pas trop les fonctions lambda :

Une instruction comme :
self._tab.setcreatefunction(lambda row, self=self:self._createflight())

Provoque l'erreur :
Using variable 'self' before assigment

Dans mon instruction, je mets le self=self parce qu'en Python 2.1, si on
ne le met pas, cela provoque une erreur :

SyntaxWarning: local name 'self' in 'mafonction' shadows use of 'self'
as global in nested scope 'lambda'

et la fonction ne fonctionne pas !!

Depuis Python 2.3, ce n'est plus obligatoire, mais mon code doit
fonctionner sous Python 2.1, donc je le laisse.

S'agit-il d'un bug de PyLint ?

Je sais qu'il y a toujours moyen d'éviter les fonctions lambda en les
détaillant, mais quand ce n'est qu'un problème d'arguments, c'est unpeu
dommage je trouve. De plus, je pense que PyLint n'est pas expressément
contre ces fonctions puisque quand on n'initialise pas de variables, il
ne dit rien.

Sébastien Aubry

8 réponses

Avatar
Sylvain Thenault
On Wed, 11 May 2005 13:38:54 +0200, Sebastien Aubry wrote:

Bonjour,


bonjour

Une instruction comme :
self._tab.setcreatefunction(lambda row, self=self:self._createflight())

Provoque l'erreur :
Using variable 'self' before assigment

[SNIP]


S'agit-il d'un bug de PyLint ?


oui, ce bug est corrigé dans la version CVS de pylint. Une nouvelle
version ne devrait pas tarder...

--
Sylvain Thénault LOGILAB, Paris (France).

http://www.logilab.com http://www.logilab.fr http://www.logilab.org

Avatar
F. Petitjean
Bonjour,

Je me suis récemment mis à utiliser PyLint pour améliorer la qualité de
mon code Python.
Je trouve ça très bien (cela m'a fait faire beaucoup de progrès), mais
j'ai l'impression qu'il n'aime pas trop les fonctions lambda :
Il me semble qu'il n'y a pas que pylint dans ce cas.


Une instruction comme :
self._tab.setcreatefunction(lambda row, self=self:self._createflight())

Provoque l'erreur :
Using variable 'self' before assigment

Dans mon instruction, je mets le self=self parce qu'en Python 2.1, si on
ne le met pas, cela provoque une erreur :

SyntaxWarning: local name 'self' in 'mafonction' shadows use of 'self'
as global in nested scope 'lambda'
Ce genre de message n'est pas à prendre au pied de la lettre. Par

exemple avec
def traitefichier(fname):
"""bla bla bla"""

if __name__ == '__main__':
"""test minimum"""
fname = 'toto'
res = traitefichier(fname)

il me semble que pylint se rebiffe d'une manière comparable. Il est vrai
que l'espace de noms global est utilisé dans le cas d'un script
(__name__ == '__main__') mais il y a un peu trop de zèle de la part de
pylint (avertissement non valable) et au contraire il devrait y avoir un
avertissement pour les modules qui ne peuvent pas être à la fois comme
module et comme script.

et la fonction ne fonctionne pas !!


Je ne comprends pas : avec ou sans pylint ? (traceback ?)
essayez :
self._tab.setcreatefunction(self._createflight)
puisqu'il semblerait que 'self' soit défini (self._tab est bien trouvé)
et que vous n'utilisiez pas la variable row.



Avatar
Sebastien Aubry
F. Petitjean wrote:
et la fonction ne fonctionne pas !!


Je ne comprends pas : avec ou sans pylint ? (traceback ?)
essayez :
self._tab.setcreatefunction(self._createflight)
puisqu'il semblerait que 'self' soit défini (self._tab est bien trouvé)
et que vous n'utilisiez pas la variable row.


Bonjour, et merci pour votre réponse.

En effet, je n'utilise pas la variable row, c'est bien pour ça que je
procède ainsi :
self._tab appelle sa "createfunction" avec un argument, row, dont je me
contrefiche pour cet abonné.

self._tab.setcreatefunction(self._createflight) provoquerait une erreur,
puisque self._createflight ne prend pas d'argument, et que self._tab lui
en passerait un à chaque événement.

C'est bien pour ça que j'écris :

self._tab.setcreatefunction(lambda row, self=self:self._createflight())

Ainsi self._tab appelle sa "createfunction" avec un argument, et la
fonction lambda appelle juste self._createflight sans argument.
J'utilise les fonctions lambda comme des "wrappers" simples qui changent
juste le nombre ou l'ordre des arguments.

Et ce que je disais, c'est que j'écrirais bien :

self._tab.setcreatefunction(lambda row:self._createflight())

Mais ce n'était pas valide en Python 2.1 (ça l'est depuis 2.3 voire 2.2).


Avatar
Sebastien Aubry
Sylvain Thenault wrote:
On Wed, 11 May 2005 13:38:54 +0200, Sebastien Aubry wrote:

Bonjour,


bonjour

Une instruction comme :
self._tab.setcreatefunction(lambda row, self=self:self._createflight())

Provoque l'erreur :
Using variable 'self' before assigment

[SNIP]


S'agit-il d'un bug de PyLint ?


oui, ce bug est corrigé dans la version CVS de pylint. Une nouvelle
version ne devrait pas tarder...


Merci de me permettre ainsi d'accéder enfin au 10/10 :-))


Avatar
Guillaume Bouchard
Sebastien Aubry wrote:
Merci de me permettre ainsi d'accéder enfin au 10/10 :-))


Je trouve quand même que cette lib à de gros defauts.

1) Ne pas autoriser les vars courtes dans certains cas (list
comprehension). Cela me lourde de devoir ecrire [machin for machine in
variable]. De même, pourquoi m'engeuler quand j'utiliser f=open('file')
dans un bout de script de 3 lignes.

2) Ne pas autoriser l'utilisation de nom de variables telle que
file/list/str. Dans certaines fonctions il est logique de donner ces
noms là. ALors pour eviter de devoir penser à un nom different, je
l'écrit en français, vous ne pensez pas qu'il vaut mieux un

file = open('truc') plutot que fichier = open('truc') pour la portablité e ?

Qu'en pensez vous ?

--
Guillaume.

Avatar
Sebastien Aubry
Guillaume Bouchard wrote:
Sebastien Aubry wrote:

Merci de me permettre ainsi d'accéder enfin au 10/10 :-))


Je trouve quand même que cette lib à de gros defauts.

1) Ne pas autoriser les vars courtes dans certains cas (list
comprehension). Cela me lourde de devoir ecrire [machin for machine in
variable]. De même, pourquoi m'engeuler quand j'utiliser f=open('file')
dans un bout de script de 3 lignes.


En effet, la règle actuelle est peut-être un peu trop restrictive.
Peut-être faudrait-il autoriser les variables courtes si leur portée ne
dépasse pas 3 lignes :

accepter :

code
x = truc
print x
code

mais pas :

x = truc
code
code
print x

dans tout les cas, il paraît indispensable de les accepter dans les
constructions à la [f(x) for x in mylist].
D'ailleurs, pour les fonctions lambda, Pylint ne dit rien quand on écrit
lambda x:f(x).

Ainsi, on a le droit d'écrire :

map(lambda x:x.method(), mylist)

mais pas :

[x.method() for x in mylist]

alors que la deuxième construction est plus lisible.

2) Ne pas autoriser l'utilisation de nom de variables telle que
file/list/str. Dans certaines fonctions il est logique de donner ces
noms là. ALors pour eviter de devoir penser à un nom different, je
l'écrit en français, vous ne pensez pas qu'il vaut mieux un

file = open('truc') plutot que fichier = open('truc') pour la portablité
e ?

Qu'en pensez vous ?


Là, par contre, c'est vraiment dangereux d'utiliser des variables
nommées ainsi, car ce sont des mots-clés du langage.
Personnellement j'écris plutôt file_ = open('truc') car je me suis déjà
fait avoir dans ce genre de cas :

map = "france"
code
code
code
print map(function, mylist)


TypeError: 'str' object is not callable

C'est un exemple (trop) simple, mais il en existe de plus complexes.

Sébastien Aubry


Avatar
Sebastien Aubry
Guillaume Bouchard wrote:
Sebastien Aubry wrote:

Merci de me permettre ainsi d'accéder enfin au 10/10 :-))


Je trouve quand même que cette lib à de gros defauts.

1) Ne pas autoriser les vars courtes dans certains cas (list
comprehension). Cela me lourde de devoir ecrire [machin for machine in
variable]. De même, pourquoi m'engeuler quand j'utiliser f=open('file')
dans un bout de script de 3 lignes.


En effet, la règle actuelle est un peu trop restrictive.
Peut-être faudrait-il autoriser les variables courtes si leur portée ne
dépasse pas 3 lignes :

accepter :

code
x = truc
print x
code

mais pas :

x = truc
code
code
print x

dans tout les cas, il paraît indispensable de les accepter dans les
constructions à la [f(x) for x in mylist].
D'ailleurs, pour les fonctions lambda, Pylint ne dit rien quand on écrit
lambda x:f(x).

Ainsi, on a le droit d'écrire :

map(lambda x:x.method(), mylist)

mais pas :

[x.method() for x in mylist]

alors que la deuxième construction est plus lisible.

2) Ne pas autoriser l'utilisation de nom de variables telle que
file/list/str. Dans certaines fonctions il est logique de donner ces
noms là. ALors pour eviter de devoir penser à un nom different, je
l'écrit en français, vous ne pensez pas qu'il vaut mieux un

file = open('truc') plutot que fichier = open('truc') pour la portablité
e ?

Qu'en pensez vous ?


Là, par contre, c'est vraiment dangereux d'utiliser des variables
nommées ainsi, car ce sont des mots-clés du langage.
Personnellement j'écris plutôt file_ = open('truc') car je me suis déjà
fait avoir dans ce genre de cas :

map = "france"
code
code
code
print map(function, mylist)


TypeError: 'str' object is not callable

C'est un exemple (trop) simple, mais il en existe de plus complexes.

Sébastien Aubry


Avatar
Tibi
Sebastien Aubry wrote:

Là, par contre, c'est vraiment dangereux d'utiliser des variables
nommées ainsi, car ce sont des mots-clés du langage.
Personnellement j'écris plutôt file_ = open('truc') car je me suis déjà


Ce n'est pas un mot-clef, c'est une fonction build-in, mais on se
comprend :)

j'utilise plutot
configFile = file('file name')
ou inputFile etc.. bref un nom qui done un tout petit peu plus d'info sur ce
fichier sans pour autant être trop long.