2016-11-03 1 views
5

私はやってみたい:__rmod__を使ってstrの%動作を上書きすることはできますか?

行うのに十分に簡単です
x %doSomething% y 

STRはxの場合を除き、任意のxとyのいずれかのために(以下のコードを参照してください)。

(1%doSomthingがTypeErrorで失敗するのと同様に)古いスタイルの文字列の書式設定を失敗させ、doSomethingで定義されている__rmod__メソッドに戻す方法はありますか(特別なメソッドを追加する、オブジェクト?

class BinaryMessage(object): 
    def __init__(self, fn): 
    self._fn = fn 
    def __rmod__(self, LHS): 
    return BinaryMessagePartial(self._fn, LHS) 

class BinaryMessagePartial(object): 
    def __init__(self, fn, LHS): 
    self._fn = fn 
    self._LHS = LHS 
    def __mod__(self, RHS): 
    return self._fn(self._LHS, RHS) 

def _doSomething(a , b): 
    return a + b 

doSomething = BinaryMessage(_doSomething) 

result = 5 %doSomething% 6 
assert result == 11 
+2

明快にするには: "foo"%doSomething% "bar" 'は' 'foobar" 'を返しますか? 'str .__ mod__'は' NotImplemented'を返すのではなく 'TypeError'を発生させるので、これは不可能だと私は信じています。 – L3viathan

+0

@MartijnPieters私はあなたの答えで働いているとは思わない。それは問題のように整数などで動作しますが、 '' foo "%doSomething%" bar "'は同じTypeErrorを発生させます。 – L3viathan

+0

@ L3viathan:いいえ、私はここで少し先に進んでいました。これは実際にはPythonのバグです、私の意見です。 –

答えて

7

:私は、Python 2.7のパッチを提出し、そして3.5とアップ。これらは着陸し、2.7.14,3.5.4,3.6.1,3.7の一部であり、ここでOPの例は期待通りに機能する。古いバージョンについては、下記を参照してください。


残念ながら、これは現在Pythonでは不可能です。動作は、評価ループにハードコードされ:(PyUnicodeは、Python str型でPython 3.5 source code、から)

TARGET(BINARY_MODULO) { 
    PyObject *divisor = POP(); 
    PyObject *dividend = TOP(); 
    PyObject *res = PyUnicode_CheckExact(dividend) ? 
     PyUnicode_Format(dividend, divisor) : 
     PyNumber_Remainder(dividend, divisor); 

に置き換えると、右側のオペランドにサブクラスを使用してLHS.__mod__メソッドを呼び出さないようにすることができます。これは残念です。 documentationから:

:右オペランドの型は、左オペランドの型のサブクラスであり、そのサブクラスが操作に反映する方法を提供している場合は、左のオペランドの非反映する前に、このメソッドが呼び出されます方法。この動作により、サブクラスは先祖操作をオーバーライドできます。

これは、ここでの唯一の選択肢だったでしょう、str % otherは(実際str.__mod__ methodのみRHSためstrオブジェクトを受け入れますが、この場合には呼び出されない)NotImplementedすべて RHSタイプが受け入れられる返すことはありません。

これは、issue #28598として提出されたPythonのバグです。

+0

Thx。決定的な答えを得るのは非常にいいです。 – DangerMouse

+0

Th3からL3viathanへ、最初は問題を指摘し、MartijnPietersは掘り下げてバグトラックを開始しました。私の選択した回避策は '__mul__'と' __rmul__'を使うことです。したがって 'result = 4 * plus * 5' – DangerMouse

関連する問題