4
>>> def mod2(n):
...   print 'the remainder is', n % 2
... 
>>> mod2(5)
the remainder is 1
>>> mod2(2)
the remainder is 0
>>> mod2('%d')
the remainder is 2
>>> mod2('%d\rHELLO. I AM A POTATO!')
HELLO. I AM A POTATO!

有没有办法禁止%符号 ( operator.mod) 做古怪的字符串替换?如果我需要类似的东西,我总是使用str.format它,并且通常宁愿这个字符串替换功能根本不存在,TypeError而是给出一个。

4

6 回答 6

4

如果你想确保它n是一个数字,我认为最简单的方法是预先对其执行数字运算:

def mod2(n):
    n - 1
    print 'the remainder is', n % 2

这将确保 aTypeError将被提出,因为您不能从字符串中删除,而您可以从所有数字类型中删除。

您可能希望将它包围在 try/catch 块中并引发您自己的异常,这对实际问题的描述性更强。

另请注意,在存储您的数据类型时可能需要更加小心。虽然 Python 是鸭子类型的,但遇到可以传入数字或字符串的情况有点奇怪。说明它不能正确处理字符串的注释可能是正确的调用。

于 2012-12-11T11:49:38.203 回答
4

你不能用开关禁用它,不。该str()类型实现了一种处理格式的__mod__方法,这并不是 Python 将表达式仅用于字符串。

因此,为防止这种情况发生,您要么需要将n参数转换为非字符串(int()例如通过将其转换为),要么需要子类str()来覆盖该__mod__方法:

>>> class noformattingstr(str):
...     def __mod__(self, other):
...         raise TypeError('String formatting using "%" has been deprecated')
... 
>>> noformattingstr('hello world: %d') % 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __mod__
TypeError: String formatting using "%" has been deprecated

您可以将其分配给__builtins__.str,但这并不意味着所有字符串文字都将使用您的子类。您必须将str()值显式转换为noformattingstr()实例。

于 2012-12-11T11:50:07.417 回答
0

在函数中使用 int() 强制转换 n。

def mod2(n):
    print 'the remainder is', int(n) % 2
于 2012-12-11T11:42:59.883 回答
0

我不知道为什么 eumiro 删除了他的答案,但这也是我的建议。除了我会明确检查类型以查找不受支持的类型,以使其对实际支持模运算符(如浮点数)的类型保持开放:

def mod2(n):
    if isinstance(n, basestring): # for Py3 use `isinstance(n, str)`
        raise TypeError('unsupported type')
    else:
        print 'the remainder is', n % 2
于 2012-12-11T11:49:45.467 回答
0

即使可以,您也不想这样做;大量代码仍然使用%字符串格式化方法,包括 Python 库中的代码。

%运算符编译为操作BINARY_MODULO码:

>>> dis.dis(mod2)
  2           0 LOAD_CONST               1 ('the remainder is')
              3 PRINT_ITEM          
              4 LOAD_FAST                0 (n)
              7 LOAD_CONST               2 (2)
             10 BINARY_MODULO       
             11 PRINT_ITEM          
             12 PRINT_NEWLINE       
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        

这意味着在不修改参数的情况下无法阻止字符串格式化;如果您想允许任意数字类型在您的代码中工作,那么您需要允许它们以自己的方式处理模运算,即使用%运算符。

要检查参数是否为数字类型,请使用numbers

from number import Number
if not isinstance(n, Number):
    raise TypeError(n)
于 2012-12-11T11:53:02.287 回答
0
def mod2(n):
    print('the remainder is %d' % (n % 2))

mod2(5)
# the remainder is 1
mod2('%d\rHELLO. I AM A POTATO!')
# TypeError: %d format: a number is required, not str
于 2012-12-11T11:39:18.883 回答