namedtuple
のPythonのオブジェクトの長さメソッドをオーバーライドするのは、予想以上に面倒な作業です。素朴なアプローチ、namedtuple._makeが戻り値の長さをチェックするのはなぜですか?
from collections import namedtuple
class Rule(namedtuple('Rule', ['lhs', 'rhs'])):
def __len__(self):
return len(self.rhs)
r = Rule('S', ['NP', 'Infl', 'VP'])
new_r = r._replace(lhs='CP') # raises a TypeError
は動作しません。それは、興味深いことに
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Rule object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
:あなたは(_source
属性として利用可能である)クラスの実際のソースコードを調べる場合は、_make
(どの_replace
コールとエラーが発生します)このように実装されていることがわかります戻り値の長さが2であることを確認します。これにより、_make
は、2以外の長さの値を返す場合に文句を言うので、タプルの__len__
メソッドをオーバーライドするのが難しくなります。
常に2から01を返す "len
"関数を渡してこの動作を防ぎます:
from collections import namedtuple
class Rule(namedtuple('Rule', ['lhs', 'rhs'])):
def _make(self, *args, len=lambda _: 2, **kwargs):
return super()._make(*args, len=len, **kwargs)
def __len__(self):
return len(self.rhs)
r = Rule('S', ['NP', 'Infl', 'VP'])
new_r = r._replace(lhs='CP') # fine
私の質問は、なぜこの長さのチェックが最初の場所で必然であり、それはそれをしないよう_make
を上書きすることは安全ですか?
"Pythonでnamedtupleオブジェクトの長さメソッドをオーバーライドするのは、あなたが予想していたよりもはるかに面倒です - なぜそうしますか?このバグに加えて、すべての種類のバグを引き起こす恐ろしい考えのようです。 – user2357112