2012-12-11 54 views
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代替。是否有可能阻止%的字符串替換在Python

+0

對不起球員,我不問我怎麼可以重新實現'mod2' ..我問我,如果這該語言的尷尬/不必要的功能可以被禁用 - 類似於你可以用'__future__'改變'/'的行爲。 – wim

+2

你不能。 'str()'類型實現了一個'__mod__'方法來處理插值。 –

+0

你不能,這是一個功能。 ;-)但是,字符串的模數沒有多大意義,否則。所以只是「施放」它。 – Keith

回答

4

你不能用一個開關禁用它,沒有。該str()型實現了__mod__ method處理的格式,它不是了Python特例,表達只是用於字符串。

因此,爲了防止這種情況,你要麼需要(通過將其轉換爲int()爲例)的n參數轉換爲東西是字符串或子類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()實例來代替。

+1

雖然一個很好的理論解決方案,在實踐中使用它是一個可怕的想法。 –

+0

同意,我不相信你認真地建議猴子修補內置類型。 – poke

+2

@Lattyware:絕對同意,但OP特意要求如何禁用它。這兩個方向都很難看。 –

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

這假定所有的提問者實際上想要做的是打印價值,這可能並非如此。 –

+0

我認爲這實際上是一個很好的技巧,但它對於非整數不會起作用。 – poke

0

在函數中用int()方法強制轉換n。

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

但是,對於其他數字類型,這會中斷。 '3.14%2'。 – poke

+0

的確如此。更好的解決方法是使用預先設置的實際參數調用該方法,以便該函數更具可重用性。在這種情況下,該函數當然不包含強制轉換。 –

+1

此外,它將適用於像'mod2('123')'這可能會導致一些不幸的行爲(當在一個稍微複雜的代碼中使用時)。除非'__doc__'明確指定參數在可能的情況下轉換爲int。 –

4

如果你想確保n是一個數字,我認爲最簡單的方法,就是用它事先進行數值運算:

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

這將確保一個TypeError會因爲你不能從字符串中取出,而你可以從所有數字類型中取出。

你可能想包圍一個try/catch塊,並提高自己的異常是多一點的描述實際的問題。

至於另一個音符,它可能只是價值要更小心你存儲的數據類型。雖然Python是duck類型的,但是有一個數字或字符串可以傳入的情況有點奇怪。一個說明它不能正確處理字符串的註釋可能是正確的調用。

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

如果你要打字檢查一個字符串,只需檢查2.x中的'basestr'或3.x中的'str'。 –

+0

@Lattyware好點! – poke

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) 
+0

'BINARY_MODULO'使用'__mod__'方法(如果存在的話); 'str()'實現該方法。 –