What does the percentage sign mean in Python

Modulus operator; gives the remainder of the left value divided by the right value. Like:

3 % 1 would equal zero (since 3 divides evenly by 1)

3 % 2 would equal 1 (since dividing 3 by 2 results in a remainder of 1).


What does the percentage sign mean?

It's an operator in Python that can mean several things depending on the context. A lot of what follows was already mentioned (or hinted at) in the other answers but I thought it could be helpful to provide a more extensive summary.

% for Numbers: Modulo operation / Remainder / Rest

The percentage sign is an operator in Python. It's described as:

x % y       remainder of x / y

So it gives you the remainder/rest that remains if you "floor divide" x by y. Generally (at least in Python) given a number x and a divisor y:

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

For example if you divide 5 by 2:

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

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

In general you use the modulo operation to test if a number divides evenly by another number, that's because multiples of a number modulo that number returns 0:

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

>>> 81 % 9  # 81 is 9 * 9
0

That's how it's used in your example, it cannot be a prime if it's a multiple of another number (except for itself and one), that's what this does:

if n % x == 0:
    break

If you feel that n % x == 0 isn't very descriptive you could put it in another function with a more descriptive name:

def is_multiple(number, divisor):
    return number % divisor == 0

...

if is_multiple(n, x):
    break

Instead of is_multiple it could also be named evenly_divides or something similar. That's what is tested here.

Similar to that it's often used to determine if a number is "odd" or "even":

def is_odd(number):
    return number % 2 == 1

def is_even(number):
    return number % 2 == 0

And in some cases it's also used for array/list indexing when wrap-around (cycling) behavior is wanted, then you just modulo the "index" by the "length of the array" to achieve that:

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

Note that there is also a function for this operator in the standard library operator.mod (and the alias operator.__mod__):

>>> import operator
>>> operator.mod(5, 2)  # equivalent to 5 % 2
1

But there is also the augmented assignment %= which assigns the result back to the variable:

>>> a = 5
>>> a %= 2  # identical to: a = a % 2
>>> a
1

% for strings: printf-style String Formatting

For strings the meaning is completely different, there it's one way (in my opinion the most limited and ugly) for doing string formatting:

>>> "%s is %s." % ("this", "good") 
'this is good'

Here the % in the string represents a placeholder followed by a formatting specification. In this case I used %s which means that it expects a string. Then the string is followed by a % which indicates that the string on the left hand side will be formatted by the right hand side. In this case the first %s is replaced by the first argument this and the second %s is replaced by the second argument (good).

Note that there are much better (probably opinion-based) ways to format strings:

>>> "{} is {}.".format("this", "good")
'this is good.'

% in Jupyter/IPython: magic commands

To quote the docs:

To Jupyter users: Magics are specific to and provided by the IPython kernel. Whether magics are available on a kernel is a decision that is made by the kernel developer on a per-kernel basis. To work properly, Magics must use a syntax element which is not valid in the underlying language. For example, the IPython kernel uses the % syntax element for magics as % is not a valid unary operator in Python. While, the syntax element has meaning in other languages.

This is regularly used in Jupyter notebooks and similar:

In [1]:  a = 10
         b = 20
         %timeit a + b   # one % -> line-magic

54.6 ns ± 2.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]:  %%timeit  # two %% -> cell magic 
         a ** b

362 ns ± 8.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

The % operator on arrays (in the NumPy / Pandas ecosystem)

The % operator is still the modulo operator when applied to these arrays, but it returns an array containing the remainder of each element in the 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])

Customizing the % operator for your own classes

Of course you can customize how your own classes work when the % operator is applied to them. Generally you should only use it to implement modulo operations! But that's a guideline, not a hard rule.

Just to provide a simple example that shows how it works:

class MyNumber(object):
    def __init__(self, value):
        self.value = value

    def __mod__(self, other):
        print("__mod__ called on '{!r}'".format(self))
        return self.value % other

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

This example isn't really useful, it just prints and then delegates the operator to the stored value, but it shows that __mod__ is called when % is applied to an instance:

>>> a = MyNumber(10)
>>> a % 2
__mod__ called on 'MyNumber(10)'
0

Note that it also works for %= without explicitly needing to implement __imod__:

>>> a = MyNumber(10)
>>> a %= 2
__mod__ called on 'MyNumber(10)'

>>> a
0

However you could also implement __imod__ explicitly to overwrite the augmented assignment:

class MyNumber(object):
    def __init__(self, value):
        self.value = value

    def __mod__(self, other):
        print("__mod__ called on '{!r}'".format(self))
        return self.value % other

    def __imod__(self, other):
        print("__imod__ called on '{!r}'".format(self))
        self.value %= other
        return self

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

Now %= is explicitly overwritten to work in-place:

>>> a = MyNumber(10)
>>> a %= 2
__imod__ called on 'MyNumber(10)'

>>> a
MyNumber(0)

While this is slightly off-topic, since people will find this by searching for "percentage sign in Python" (as I did), I wanted to note that the % sign is also used to prefix a "magic" function in iPython: https://ipython.org/ipython-doc/3/interactive/tutorial.html#magic-functions


The % does two things, depending on its arguments. In this case, it acts as the modulo operator, meaning when its arguments are numbers, it divides the first by the second and returns the remainder. 34 % 10 == 4 since 34 divided by 10 is three, with a remainder of four.

If the first argument is a string, it formats it using the second argument. This is a bit involved, so I will refer to the documentation, but just as an example:

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

However, the string formatting behavior is supplemented as of Python 3.1 in favor of the string.format() mechanism:

The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer str.format() interface helps avoid these errors, and also provides a generally more powerful, flexible and extensible approach to formatting text.

And thankfully, almost all of the new features are also available from python 2.6 onwards.