Python中的百分号什么意思

79 投票
8 回答
328780 浏览
提问于 2025-04-15 12:05

在这个教程里,有一个关于找质数的例子:

>>> 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')
...

我知道双等号 == 是用来判断两个东西是否相等的,但我不太明白 if n % x 这一部分。虽然我能逐步说出每个部分的意思,但我不明白百分号是怎么回事。

if n % x 实际上是什么意思呢?

8 个回答

38

百分号代表什么?

在Python中,百分号是一个运算符,根据上下文可以有几种不同的意思。接下来我会详细总结一下,很多内容在其他回答中已经提到过了。

% 用于数字:取模运算 / 余数

百分号是Python中的一个运算符。它的作用是:

x % y       remainder of x / y

它给你提供了如果用x除以y后剩下的余数。一般来说(至少在Python中),给定一个数字x和一个除数y

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

例如,如果你用5除以2:

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

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

通常你会用取模运算来测试一个数字是否能被另一个数字整除,因为一个数字的倍数取模这个数字会返回0:

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

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

在你的例子中,如果一个数字是另一个数字的倍数(除了它自己和1),那么它就不能是质数,这就是这个运算的作用:

if n % x == 0:
    break

如果你觉得n % x == 0不太好理解,可以把它放在另一个函数里,起个更容易理解的名字:

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

...

if is_multiple(n, x):
    break

比如可以叫evenly_divides,这就是在这里测试的内容。

类似地,它常用来判断一个数字是“奇数”还是“偶数”:

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

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

在某些情况下,它也用于数组或列表的索引,当你想要循环的效果时,可以用“索引”对“数组长度”取模来实现:

>>> 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

注意,标准库中也有这个运算符的函数operator.mod(还有别名operator.__mod__):

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

另外,还有一个增强赋值运算%=,它会把结果重新赋值给变量:

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

% 用于字符串:printf风格的字符串格式化

在字符串中,百分号的意思完全不同,它是用来做字符串格式化的一种方式(我觉得这种方式比较有限且不太美观):

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

这里字符串中的%代表一个占位符,后面跟着格式说明。在这个例子中,我用了%s,表示期待一个字符串。然后字符串后面跟着一个%,表示左边的字符串会被右边的内容格式化。在这个例子中,第一个%s会被第一个参数this替换,第二个%s会被第二个参数(good)替换。

注意,还有很多更好的(可能是个人观点)字符串格式化方式:

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

% 在Jupyter/IPython中:魔法命令

引用文档

对于Jupyter用户:魔法命令是特定于IPython内核的。是否在某个内核中提供魔法命令是由内核开发者决定的。魔法命令必须使用一种在底层语言中无效的语法元素才能正常工作。例如,IPython内核使用%作为魔法命令的语法元素,因为%在Python中不是有效的单目运算符,而在其他语言中则有意义。

这在Jupyter笔记本和类似环境中经常使用:

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)

% 运算符在数组中(在NumPy / Pandas生态系统中)

在这些数组上,%运算符仍然是取模运算,但它返回一个包含数组中每个元素余数的数组:

>>> 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])

自定义%运算符用于自己的类

当然,你可以自定义当%运算符应用于自己的类时的行为。一般来说,你应该只用它来实现取模运算!但这只是个指导原则,并不是硬性规定。

这里给个简单的例子,展示它是如何工作的:

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)

这个例子其实没什么用,只是打印一下,然后把运算符委托给存储的值,但它展示了当%应用于一个实例时,__mod__会被调用:

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

注意,它也适用于%=,而不需要显式实现__imod__

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

>>> a
0

不过你也可以显式实现__imod__来覆盖增强赋值:

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)

现在%=被显式覆盖以在原地工作:

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

>>> a
MyNumber(0)
164

百分号 % 有两个作用,具体取决于它后面的内容。在这个例子中,它作为取余运算符使用,也就是说当它的参数是数字时,它会把第一个数字除以第二个数字,然后返回一个余数。比如说,34 % 10 == 4,因为34除以10等于3,余下4。

如果第一个参数是一个字符串,它会用第二个参数来格式化这个字符串。这部分有点复杂,所以我会参考一下文档,但我可以给你一个简单的例子:

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

不过,从Python 3.1开始,字符串格式化的方式有了更新,推荐使用字符串.format()的方法:

这里描述的格式化操作有很多小问题,容易导致一些常见错误(比如无法正确显示元组和字典)。使用更新的str.format()接口可以帮助避免这些错误,并且提供了一种更强大、更灵活和可扩展的文本格式化方式。

幸运的是,几乎所有的新特性在Python 2.6及之后的版本中也都可以使用。

74

取模运算符;它会给出左边的数除以右边的数的余数。比如:

3 % 1 的结果是零(因为3除以1是整除,没有余数)

3 % 2 的结果是1(因为3除以2会剩下1)。

撰写回答