是否可以防止python中的字符串替换百分比

时间:2012-12-11 11:33:10

标签: python string substitution

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

6 个答案:

答案 0 :(得分:4)

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

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

这样可以确保TypeError会被提升,因为您无法从字符串中删除,而您可以使用所有数字类型。

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

另外请注意,存储您的数据类型可能更值得注意。虽然Python是鸭子类型,但是有一个数字或字符串可以传入的情况有点奇怪。说明它不能正确处理字符串的说明可能是正确的调用。

答案 1 :(得分:4)

你不能用开关禁用它,没有。 str()类型实现了一个__mod__ method来处理格式化,而不是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()个实例。

答案 2 :(得分: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

答案 3 :(得分:0)

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

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

答案 4 :(得分: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

答案 5 :(得分: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)