68 votos

¿Qué significa el signo de porcentaje en Python?

En el tutorial hay un ejemplo para encontrar números primos:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...

Entiendo que el doble == es una prueba de igualdad, pero no entiendo la parte if n % x. Puedo explicar verbalmente cada parte y decir qué hace la declaración para el ejemplo. Pero no entiendo cómo se relaciona el signo de porcentaje.

¿Qué significa realmente if n % x?

153voto

IfLoop Puntos 59461

El % hace dos cosas, dependiendo de sus argumentos. En este caso, actúa como el operador módulo, lo que significa que cuando sus argumentos son números, divide el primero por el segundo y devuelve el resto. 34 % 10 == 4 ya que 34 dividido por 10 es tres, con un resto de cuatro.

Si el primer argumento es una cadena, la formatea utilizando el segundo argumento. Esto es un poco complicado, por lo que me remitiré a la documentación, pero solo como ejemplo:

>>> "foo %d bar" % 5
'foo 5 bar'

Sin embargo, el comportamiento de formato de cadenas se complementa a partir de Python 3.1 en favor del mecanismo de cadena.format():

Las operaciones de formato descritas aquí muestran una variedad de peculiaridades que conducen a una serie de errores comunes (como no mostrar correctamente las tuplas y diccionarios). Usar la nueva interfaz de str.format() ayuda a evitar estos errores, y también proporciona un enfoque generalmente más potente, flexible y extensible para formatear texto.

Y afortunadamente, casi todas las nuevas funciones también están disponibles desde python 2.6 en adelante.

73voto

inkedmn Puntos 12655

Operador de módulo; devuelve el resto del valor de la izquierda dividido por el valor de la derecha. Por ejemplo:

3 % 1 sería igual a cero (ya que 3 se divide uniformemente por 1)

3 % 2 sería igual a 1 (ya que dividir 3 por 2 resulta en un residuo de 1).

35voto

MSeifert Puntos 6307

¿Qué significa el signo de porcentaje?

Es un operador en Python que puede significar varias cosas dependiendo del contexto. Mucho de lo que sigue ya fue mencionado (o insinuado) en las otras respuestas, pero pensé que podría ser útil proporcionar un resumen más extenso.

% para números: Operación Módulo / Resto

El signo de porcentaje es un operador en Python. Se describe como:

x % y       resto de x / y

Por lo tanto, te da el resto que queda si divides x por y. Generalmente (al menos en Python) dado un número x y un divisor y:

x == y * (x // y) + (x % y)

Por ejemplo, si divides 5 por 2:

>>> 5 // 2
2
>>> 5 % 2
1

>>> 2 * (5 // 2) + (5 % 2)
5

En general, se utiliza la operación módulo para probar si un número se divide de manera uniforme por otro número, eso se debe a que los múltiplos de un número módulo ese número devuelven 0:

>>> 15 % 5  # 15 es 3 * 5
0

>>> 81 % 9  # 81 es 9 * 9
0

Así es como se usa en tu ejemplo, no puede ser un número primo si es un múltiplo de otro número (excepto por él mismo y uno), eso es lo que hace esto:

if n % x == 0:
    break

Si sientes que n % x == 0 no es muy descriptivo, podrías ponerlo en otra función con un nombre más descriptivo:

def es_multiplo(numero, divisor):
    return numero % divisor == 0

...

if es_multiplo(n, x):
    break

En lugar de es_multiplo también podría llamarse divide_uniformemente o algo similar. Eso es lo que se prueba aquí.

Similar a eso, a menudo se usa para determinar si un número es "impar" o "par":

def es_impar(numero):
    return numero % 2 == 1

def es_par(numero):
    return numero % 2 == 0

Y en algunos casos también se utiliza para indexar arreglos/listas cuando se quiere un comportamiento de envoltura (ciclismo), entonces simplemente haces módulo del "índice" por la "longitud del arreglo" para lograr eso:

>>> l = [0, 1, 2]
>>> longitud = len(l)
>>> for indice in range(10):
...     print(l[indice % longitud])
0
1
2
0
1
2
0
1
2
0

Nota que también hay una función para este operador en la biblioteca estándar operator.mod (y el alias operator.__mod__):

>>> import operator
>>> operator.mod(5, 2)  # equivalente a 5 % 2
1

Pero también está la asignación aumentada %= que asigna el resultado de nuevo a la variable:

>>> a = 5
>>> a %= 2  # idéntico a: a = a % 2
>>> a
1

% para strings: Formateo de strings al estilo de printf

Para strings, el significado es completamente diferente, allí es una forma (en mi opinión la más limitada y fea) de hacer formateo de strings:

>>> "%s es %s." % ("esto", "bueno") 
'esto es bueno'

Aquí el % en el string representa un marcador seguido de una especificación de formato. En este caso utilicé %s que significa que espera un string. Luego, el string va seguido por un % que indica que el string del lado izquierdo será formateado por el lado derecho. En este caso, el primer %s es reemplazado por el primer argumento esto y el segundo %s es reemplazado por el segundo argumento (bueno).

Nota que hay formas mucho mejores (probablemente basadas en opiniones) de formatear strings:

>>> "{} es {}.".format("esto", "bueno")
'esto es bueno.'

% en Jupyter/IPython: comandos mágicos

Para citar la documentación:

Para usuarios de Jupyter: Los comandos mágicos son específicos y proporcionados por el núcleo de IPython. Si los comandos mágicos están disponibles en un núcleo es una decisión que toma el desarrollador del núcleo caso por caso. Para funcionar correctamente, los comandos mágicos deben usar un elemento de sintaxis que no sea válido en el lenguaje subyacente. Por ejemplo, el núcleo de IPython utiliza el elemento de sintaxis % para comandos mágicos ya que % no es un operador unario válido en Python. Mientras que, el elemento de sintaxis tiene un significado en otros lenguajes.

Esto se usa regularmente en cuadernos Jupyter y similares:

In [1]:  a = 10
         b = 20
         %timeit a + b   # un % -> magia de línea

54.6 ns ± 2.7 ns por ciclo (media ± desviación estándar de 7 corridas, 10000000 ciclos cada)

In [2]:  %%timeit  # dos %% -> magia de celda
         a ** b

362 ns ± 8.4 ns por ciclo (media ± desviación estándar de 7 corridas, 1000000 ciclos cada)

El operador % en arrays (en el ecosistema de NumPy / Pandas)

El operador % sigue siendo el operador módulo cuando se aplica a estos arrays, pero devuelve un array con el resto de cada elemento en el array:

>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> a % 2
array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])

Personalizando el operador % para tus propias clases

Por supuesto, puedes personalizar cómo funcionan tus propias clases cuando se aplica el operador % a ellas. ¡Generalmente deberías usarlo solo para implementar operaciones módulo! Pero eso es una pauta, no una regla estricta.

Solo para proporcionar un ejemplo simple que muestra cómo funciona:

class MiNumero(object):
    def __init__(self, valor):
        self.valor = valor

    def __mod__(self, otro):
        print("__mod__ llamado en '{!r}'".format(self))
        return self.valor % otro

    def __repr__(self):
        return "{self.__class__.__name__}({self.valor!r})".format(self=self)

Este ejemplo no es realmente útil, simplemente imprime y luego delega el operador al valor almacenado, pero muestra que se llama a __mod__ cuando se aplica % a una instancia:

>>> a = MiNumero(10)
>>> a % 2
__mod__ llamado en 'MiNumero(10)'
0

Nota que también funciona para %= sin necesidad explícita de implementar __imod__:

>>> a = MiNumero(10)
>>> a %= 2
__mod__ llamado en 'MiNumero(10)'

>>> a
0

Sin embargo, también podrías implementar __imod__ explícitamente para sobrescribir la asignación aumentada:

class MiNumero(object):
    def __init__(self, valor):
        self.valor = valor

    def __mod__(self, otro):
        print("__mod__ llamado en '{!r}'".format(self))
        return self.valor % otro

    def __imod__(self, otro):
        print("__imod__ llamado en '{!r}'".format(self))
        self.valor %= otro
        return self

    def __repr__(self):
        return "{self.__class__.__name__}({self.valor!r})".format(self=self)

Ahora %= está sobrescrito explícitamente para funcionar en el lugar:

>>> a = MiNumero(10)
>>> a %= 2
__imod__ llamado en 'MiNumero(10)'

>>> a
MiNumero(0)

32voto

Stephen Puntos 1921

Aunque esto se desvía ligeramente del tema, ya que la gente encontrará esto buscando "signo de porcentaje en Python" (como yo hice), quería señalar que el signo % también se utiliza para prefijar una función "mágica" en iPython: https://ipython.org/ipython-doc/3/interactive/tutorial.html#magic-functions

1voto

Jon W Puntos 7032

En python 2.6 el operador '%' realizaba un módulo. No creo que lo hayan cambiado en 3.0.1

El operador de módulo te dice el resto de la división de dos números.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X