Header Ads Widget

Ticker

6/recent/ticker-posts

Cómo incrementar un número en Python: operadores, funciones y más

 De vez en cuando, me gusta revisar los fundamentos de Python para ver si puedo aprender algo nuevo sobre el lenguaje. En esta ocasión pensé que sería divertido ver algunas formas diferentes de incrementar un número en Python.

Resulta que existen dos formas sencillas de incrementar un número en Python. En primer lugar, se podría utilizar la asignación directa: x = x + 1Como alternativa, se podría utilizar la sintaxis operador de incremento condensada: x += 1Además, hay algunas opciones menos convencionales como usar el addmétodo del operatormódulo o usar expresiones generadoras. Siéntase libre de profundizar a continuación para obtener más información.

Descripción del problema

Al resolver problemas de programación, una operación muy común es agregar un valor fijo a un número. A esta operación la llamamos incremento y es útil en muchos contextos. Por ejemplo, es posible que queramos utilizar un número como contador, para poder realizar un número fijo de operaciones. En ese caso, probablemente comenzaríamos desde cero y agregaríamos uno hasta que se cumpla nuestra condición (por ejemplo i < 10).

Por supuesto, la forma de lograr un incremento varía según el idioma. Por ejemplo, en los lenguajes de estilo C, a menudo hay operadores de incremento directo:

1
2
3
++i
i++
i += 1

Desafortunadamente, algunas de estas opciones anteriores simplemente no funcionan en Python. Por ejemplo, tanto los operadores de preincremento (es decir ++i) como los de post-incremento (es decir i++) fallan en Python:

1
2
3
4
5
>>> i = 7
>>> i++
SyntaxError: invalid syntax
>>> ++i
7

Con el operador de incremento posterior, vemos que obtenemos un error de sintaxis evidente. En otras palabras, no es válido. Mientras tanto, el operador de incremento previo se ejecuta, pero en realidad no sucede nada. Eso es porque el operador unario más en Python no hace nada por los números. De hecho, podríamos poner tantas ventajas como queramos:

1
2
>>> +++++++++++++++++++i
7

¡Naturalmente, tendremos que buscar en otra parte si queremos incrementar un número!

Soluciones

Afortunadamente, hay algunas formas de incrementar un valor en Python. De lo contrario, ¿por qué existiría este artículo? En cualquier caso, ¡profundicemos!

Incrementar un número con asignación

Una de las cosas buenas de los números en Python es que son inmutables, lo que significa que no se pueden cambiar. De lo contrario, tendríamos que lidiar con problemas molestos como el alias. Si está interesado en aprender sobre los efectos del aliasing, tengo otro artículo que habla sobre los riesgos de copiar tipos de datos mutables .

En cualquier caso, dado que los números de Python son inmutables, podemos usarlos en aritmética y asignar su valor con facilidad:

1
2
x = 5
x = x + 1

Aquí, hemos definido una variable, xque almacena el valor 5. En la siguiente línea, tomamos xy le sumamos 1. Luego, almacenamos el resultado nuevamente en xComo resultado, las xtiendas 6.

Como alguien que enseña muchas clases de introducción a la programación, encuentro que a los estudiantes a menudo les molesta esta sintaxis la primera vez. Después de todo, la mayoría de los estudiantes están familiarizados con las =matemáticas, por lo que no han hecho la conexión que =realmente es el operador de asignación, lo que hace que la declaración sea x = x + 1muy legal.

Si esta sintaxis le molesta, mi consejo es que ignore el lado izquierdo (es decir x =). En cambio, concéntrese en lo que está sucediendo en el lado derecho de la declaración (es decir x + 1). Esta parte de la declaración se llama expresión y podemos tener literalmente cualquier cosa allí siempre que se evalúe con algún valor. En este caso, podemos evaluar la expresión directamente en tres pasos:

  1. x evalúa a 5
  2. 1 evalúa a 1
  3. 5 + 1 evalúa a 6

En este punto, el resultado se almacena nuevamente en el xque sobrescribe su valor anterior, 5.

Si este desglose de declaraciones y expresiones le parece interesante, le recomiendo que consulte mi artículo que profundiza un poco más en este tema . De lo contrario, veremos la siguiente solución.

Incrementar un número usando un operador

Como la mayoría de los lenguajes de programación, Python tiene una forma de incluir azúcar sintáctico para escenarios como incremento. Dicho esto, sólo hay un cierto operador de incremento: +=Para usarlo, necesitaremos reelaborar nuestro código de antes:

1
2
x = 5
x += 1

Como probablemente podamos imaginar, esta declaración funciona exactamente como la línea de la sección anterior. Sin embargo, hemos eliminado algunos códigos redundantes (es decir, los adicionales x).

Una de las cosas buenas de este operador es que crea una declaración independiente. En otras palabras, no se puede incrustar en otros contextos:

1
2
>>> y = x += 1
SyntaxError: invalid syntax

Compare esto con los operadores de incremento típicos en otros lenguajes como Java donde esto es posible:

1
x = x++

¿Alguna idea de lo que hace esto? Respuesta: absolutamente nada. En este ejemplo, xse incrementa. Luego, se devuelve su valor anterior y se sobrescribe el resultado. En otras palabras, xpermanece igual. Si eso suena loco, escribí un artículo completo sobre el comportamiento . Es una de las razones por las que me alegro de que la sintaxis nunca haya llegado a Python.

Incrementar un número usando una función

Una cosa que encuentro interesante sobre Python es la gran cantidad de características de lenguaje funcional que tiene. Por ejemplo, además de todos los operadores explícitos, Python incluye un conjunto de sobrecargas funcionales. Como resultado, podríamos incrementar un número sin usar un operador aritmético:

1
2
3
import operator
x = 5
x = operator.add(x, 1)

La ventaja de utilizar una función sobre el operador directo es la escalabilidad. Por ejemplo, podemos encontrar que queremos incrementar una lista completa de valores. En ese caso, la addfunción hace el truco:

1
list(map(operator.add, [1, 1, 1], [5, -4, 13]))

Por supuesto, podría ser un poco más limpio usar el __add__método subyacente :

1
list(map(1 .__add__, [5, -4, 13]))  # the space is important

Dicho esto, esta solución es probablemente la más ridícula para el caso estándar.

Incrementar un número implícitamente

A veces no tiene sentido incrementar manualmente un número. Después de todo, en la descripción de nuestro problema, hablamos de usar un número como contador en un ciclo. La mayoría de las veces, sin embargo, tratamos de evitar contadores explícitos utilizando iteradores. Por ejemplo, si quisiéramos recorrer los caracteres de una cadena, podríamos escribir lo siguiente:

1
2
3
my_string = "Bob"
for character in my_string:
  pass  # Do Something!

Observe cómo no tuvimos que incrementar explícitamente un contador. Dado que las cadenas son iterables, nos ocupamos de todo eso.

Por supuesto, a veces todavía queremos contar un poco. Después de todo, es posible que deseemos realizar una acción exactamente 5 veces. En ese caso, podemos usar un rango:

1
2
for i in range(5):
  pass  # Do Something!

Asimismo, incluso podríamos hacer nuestro propio contador usando una expresión generadora:

1
counter = (i for i in range(5))

Luego, para generar términos en la secuencia, podríamos llamar continuamente next():

1
2
3
4
>>> next(counter)
0
>>> next(counter)
1

Todas estas opciones realizan una operación de incremento implícitamente. Dependiendo de sus necesidades, eso podría tener más sentido. Por supuesto, eso depende de ti.

Bono: disminuir un número

Odiaría leer un artículo completo hablando de incrementar números sin mencionar la operación del cumplido: decremento. Sin introducir ninguna sintaxis adicional, podemos reducir un número con facilidad:

1
2
x = 10
x += -1

Por supuesto, eso es un poco contradictorio. En cambio, a menudo optamos por el operador de decremento:

1
x -= 1

Asimismo, la asignación directa funciona igual de bien:

1
x = x - 1

Además, la solución funcional que hemos mencionado se puede modificar para hacer el trabajo:

1
x = operator.sub(x, 1)

Por supuesto, como ya hemos mencionado, probablemente sea un poco excesivo hacer algo como esto. En su lugar, apégate al operador de decremento.

Actuación

Como siempre, me gusta echar un vistazo a las distintas soluciones y compararlas en términos de rendimiento. Para hacer eso, necesitaremos poner cada solución en su propia cadena:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
setup = """
import operator
"""
 
assignment = """
x = 0
x = x + 1
"""
 
increment = """
x = 0
x += 1
"""
 
function = """
x = 0
x = operator.add(x, 1)
"""
 
generator = """
x = (i for i in range(5))
next(x)
"""

Luego, para probar estas opciones, necesitaremos ejecutarlas con timeit:

1
2
3
4
5
6
7
8
9
>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=assignment))
0.03538969999999608
>>> min(timeit.repeat(setup=setup, stmt=increment))
0.03586820000001012
>>> min(timeit.repeat(setup=setup, stmt=function))
0.09383009999999103
>>> min(timeit.repeat(setup=setup, stmt=generator))
0.6202383999999768

Naturalmente, los operadores centrales hacen el trabajo más rápido, pero no me encanta la prueba del generador. Como resultado, decidí reescribirlo para que la cadena de configuración incluya el generador hasta un valor muy grande:

1
2
3
4
5
6
7
8
9
>>> setup = """
import operator
x = (i for i in range(100000000))
"""
>>> generator = """
next(x)
"""
>>> min(timeit.repeat(setup=setup, stmt=generator))
0.11321939999999131

Ahora, eso es un poco más respetable. Por supuesto, me pregunto si incluir xen la cadena de configuración también cambiará las pruebas originales:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
>>> setup = """
import operator
x = 0
"""
>>> assignment = """
x = x + 1
"""
>>> increment = """
x += 1
"""
>>> function = """
x = operator.add(x, 1)
"""
>>> min(timeit.repeat(setup=setup, stmt=assignment))
0.05624840000001541
>>> min(timeit.repeat(setup=setup, stmt=increment))
0.061655099999995855
>>> min(timeit.repeat(setup=setup, stmt=function))
0.12224320000001399

En cualquier caso, parece que la asignación directa o los operadores de incremento son la mejor opción. Para poner esto en contexto, ejecuté todas las pruebas usando Python 3.7.3 en una máquina con Windows 10.

Desafío

Cuando pensaba en un buen desafío, me costaba mucho pensar en una idea. Después de todo, hay muchos contextos diferentes en los que incrementar una variable podría ser útil, pero no es exactamente una habilidad en la que podamos desarrollar.

Como resultado, pensé que podría ser más divertido crear una función de incremento compleja que tenga varias condiciones. Por ejemplo, estas son algunas de las condiciones:

  • Si el número actual es impar, sume 1
  • Si el número actual es par, sume 3
  • Si el número actual es divisible por 5, sume 5

Como una arruga adicional, cada número deberá verificarse para los tres criterios. Por ejemplo, el número 15 es impar y divisible por 5. Como resultado, el siguiente número debe ser 21 (es decir, 15 + 5 + 1). Asimismo, el número 12 solo cumplirá los criterios pares, por lo que el siguiente número será el 15.

Como siempre, compartiré una respuesta en los comentarios. ¡Siéntete libre de compartir el tuyo también!

Un pequeño resumen

¡Y con eso, hemos terminado! Una vez más, aquí están todas las soluciones en un lugar conveniente:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
x = 0
 
# Increment by one with assignment
x = x + 1
 
# Increment by one with the increment operator
x += 1
 
# Increment by one with a function
import operator
x = operator.add(x, 1)
 
# Increment by one implicitly on an iterable
my_string = "Bob"
for character in my_string:
  pass  # Do Something!
 
# Increment by one implicitly using range
for i in range(5):
  pass  # Do Something!
 
# Increment by one implicitly using a generator expression
counter = (i for i in range(5))
next(counter)
 
# Decrement by one with assignment
x = x - 1
 
# Decrement by one with the decrement operator
x -= 1
 
# Decrement by one with a function
x = operator.sub(x, 1)

Publicar un comentario

0 Comentarios