excepciones - Python: evitar advertencias de pylint sobre demasiados argumentos
bash demasiados argumentos (8)
Quiero refactorizar una función Python grande en otras más pequeñas. Por ejemplo, considere este siguiente fragmento de código:
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
Por supuesto, este es un ejemplo trivial. En la práctica, el código es más complejo. Mi punto es que contiene muchas variables de alcance local que tendrían que pasarse a la función extraída, que podría ser como:
def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
El problema es que pylint provocaría una advertencia sobre demasiados argumentos. Podría evitar la advertencia haciendo algo como:
def mysum(d):
x1 = d[''x1'']
x2 = d[''x2'']
...
x9 = d[''x9'']
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
def mybigfunction():
...
d = {}
d[''x1''] = x1
...
d[''x9''] = x9
x = mysum(d)
pero este enfoque se vuelve feo para mí, requiere escribir mucho código que es incluso redundante.
Hay una mejor manera de hacerlo?
¿Desea una mejor manera de pasar los argumentos o simplemente una manera de evitar que el pylint
le haga pylint
un mal rato? Si es lo último, me parece recordar que podría detener el fastidio poniendo comentarios de pylint
en su código a lo largo de las líneas de:
#pylint: disable-msg=R0913
o:
#pylint: disable-msg=too-many-arguments
Recordando volver a encenderlos tan pronto como sea posible.
En mi opinión, no hay nada intrínsecamente malo en pasar muchos argumentos y las soluciones que abogan por envolverlos en algún argumento de contenedor no solucionan ningún problema, aparte de evitar que pylint
te pylint
:-).
Si necesitas pasar veinte argumentos, entonces pásalos. Puede ser que esto sea necesario porque su función está haciendo demasiado y una re-factorización podría ayudar allí, y eso es algo que debe ver. Pero no es una decisión que podamos tomar realmente a menos que veamos cuál es el código "real".
Comente sobre la respuesta de paxdiablo, ya que no tengo suficiente reputación para comentar allí directamente: - /
No me gusta referirme al número, el nombre simbólico es mucho más expresivo y evita tener que agregar un comentario que podría quedar obsoleto con el tiempo.
Así que prefiero hacer:
#pylint: disable-msg=too-many-arguments
Y también recomendaría no dejarlo allí: permanecerá activo hasta que el archivo finalice o se deshabilite, lo que ocurra primero.
Así que mejor haciendo:
#pylint: disable-msg=too-many-arguments
code_which_would_trigger_the_msg
#pylint: enable-msg=too-many-arguments
También recomendaría habilitar / deshabilitar una sola advertencia / error por línea.
Primero, uno de los epigramas de Perlis :
"Si tienes un procedimiento con 10 parámetros, probablemente te perdiste alguno".
Algunos de los 10 argumentos están presuntamente relacionados. Agruparlos en un objeto, y pasar eso en su lugar.
Dando ejemplo, porque no hay suficiente información en la pregunta para responder directamente:
class PersonInfo(object):
def __init__(self, name, age, iq):
self.name = name
self.age = age
self.iq = iq
Entonces su función de 10 argumentos:
def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7):
...
se convierte en:
def f(personinfo, x1, x2, x3, x4, x5, x6, x7):
...
y la persona que llama cambia a:
personinfo = PersonInfo(name, age, iq)
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7)
Puede cambiar fácilmente el número máximo permitido de argumentos en pylint. Simplemente abra su archivo pylintrc (genérelo si aún no tiene uno) y cambie:
max-args = 5
a:
max-args = 6 # o cualquier valor que te convenga
Del manual de pylint
Especificar todas las opciones adecuadas para su configuración y estándares de codificación puede ser tedioso, por lo que es posible usar un archivo rc para especificar los valores predeterminados. Pylint busca / etc / pylintrc y ~ / .pylintrc. La opción --generate-rcfile generará un archivo de configuración comentado de acuerdo con la configuración actual en la salida y salida estándar. Puede poner otras opciones antes de esta para usarlas en la configuración, o comenzar con los valores predeterminados y ajustar la configuración manualmente.
Puedes intentar usar la característica de argumentos variables de Python :
def myfunction(*args):
for x in args:
# Do stuff with specific argument here
Python tiene algunas herramientas de programación funcionales que pueden ajustarse a tus necesidades. Echa un vistazo a las funciones lambda y el map . Además, estás utilizando dicts cuando parece que estarías mucho mejor servido con listas. Para el ejemplo simple que proporcionaste, prueba este modismo. Tenga en cuenta que el mapa sería mejor y más rápido, pero puede que no se ajuste a sus necesidades:
def mysum(d):
s = 0
for x in d:
s += x
return s
def mybigfunction():
d = (x1, x2, x3, x4, x5, x6, x7, x8, x9)
return mysum(d)
Mencionó tener muchas variables locales, pero, francamente, si está tratando con listas (o tuplas), debe usar listas y eliminar todas esas variables locales a largo plazo.
Quizás podrías convertir algunos de los argumentos en variables miembro. Si necesitas mucho estado, una clase me suena como una buena idea.
Simplifique o divida la función para que no requiera nueve argumentos (o ignore el pylint, pero los esquivos como los que está proponiendo anulan el propósito de una herramienta de pelusas).
EDITAR: si es una medida temporal, desactive la advertencia para la función en cuestión usando un comentario como se describe aquí: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html
Más tarde, puede grep para todas las advertencias desactivadas.