在Python中,百分号符号代表字符串格式化操作。

77

在教程中有一个寻找质数的示例:

>>> 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实际上是什么意思?
9个回答

162

百分号符号 % 的行为会根据其参数而有所不同。在此情况下,它充当模数运算符,意味着当其参数为数字时,它将第一个数字除以第二个数字并返回 余数34 % 10 == 4,因为34除以10是三,余数为四。

如果第一个参数是字符串,则使用第二个参数对其进行格式化。这有点复杂,所以我会参考文档,但只作为一个例子:

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

然而,从Python 3.1开始,字符串格式化行为得到增强,支持使用string.format()机制:

这里描述的格式化操作存在各种怪癖,导致出现一些常见错误(比如不能正确地显示元组和字典)。使用更新的str.format()接口有助于避免这些错误,并且提供了一种更强大、灵活和可扩展的文本格式化方法。

值得庆幸的是,几乎所有新功能也适用于 Python 2.6 及以上版本。


2
我相信在Python 3中移除了字符串格式化运算符。 - David Z
3
@David:它已经被弃用了。 - SilentGhost
1
我也曾这样想,但当我四处寻找时却找不到。第二次查看时才发现。编辑进行了解释。 - SingleNegationElimination
4
文档中说:“%运算符配合更强大的字符串格式化方法format()使用”。我认为这并不意味着它已被移除或弃用。 - Leftium
4
@Leftium 在http://docs.python.org/3/whatsnew/3.0.html#pep-3101-a-new-approach-to-string-formatting上提到,`%`会在Python 3.1中被弃用,并且'在以后某个时间从语言中删除'。然而,该页面已经相当陈旧了。我在Python 3.2或3.3文档中找不到任何相关提及。希望开发人员已经改变了想法,决定保持%的原样。format()功能强大,但对于基本用途,%更加方便。 - TM.
1
很棒的交流,谢谢!在字符串操作中使用%符号是Python独有的吗? - Charles

75

模数运算符;它给出左侧值除以右侧值的余数。例如:

3 % 1等于零(因为3被1整除)

3 % 2等于1(因为将3除以2得到余数为1)。


4
知道一下,这被称为欧几里得除法。 - A. Gille
2
冒昧指出,取模(%)与负数的余数并不相同。-2除以3的余数为-2,但是-2 % 3 = 1。 - Riker
1
@A.Gille,进一步澄清一下,虽然这是执行欧几里得除法的结果,但这里的区别在于模运算符仅返回余数,而不返回商。 - K Paul

38

百分号在Python中是一个操作符,其含义根据上下文不同而不同。很多内容在其他答案中已经提到(或者暗示了),但我认为提供更详细的总结有助于理解。

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

百分号是Python中的一个操作符。它的描述如下:

x % y       remainder of x / y

它会给出你用 x 除以 y 的 余数,即使你使用 "floor divide"(向下取整除法)。通常来说(至少在 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 不够描述清晰,您可以将它放入另一个函数,使用更易理解的名称:

如果你觉得 n % x == 0 不是很形象化,你可以把它放到另一个函数中,用一个更具描述性的名称:

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

...

if is_multiple(n, x):
    break

除了is_multiple,也可以命名为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)

34

1
在Python 2.6中,'%'操作符执行模数运算。我认为在3.0.1版本中它没有改变。
取模运算符告诉你两个数字相除的余数。

1

它检查除法的模数。例如,在您迭代从2到n的所有数字并检查n是否可被其中任何一个数字整除的情况下,您正在检查给定数字n是否为质数。简单来说,您正在检查给定数字n是否为质数。(提示:您可以检查到n/2)。


1

取模运算符。当你将两个数字相除时,得到的余数。

例如:

>>> 5 % 2 = 1 # remainder of 5 divided by 2 is 1
>>> 7 % 3 = 1 # remainer of 7 divided by 3 is 1
>>> 3 % 1 = 0 # because 1 divides evenly into 3

0
这意味着除法运算的余数,如果有的话。如果没有余数,它会显示为0。
例如:
8 % 3 = 2
例如2:
90 % 89 = 1

这个答案没有提供任何其他答案中已经提到的信息。 - undefined

0
x % n == 0 的意思是将 x/n 和余数的值作为结果与零进行比较...
例如: 4/5==0
4/5 的余数是 4
4==0 (False)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接