はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
辞書クラスの拡張 (Python)
def __setitem__(self, key, value):
if isinstance(value, float):
value = int(round(value))
elif not isinstance(value, int):
raise PyteomicsError('Only integers allowed as values in '
'Composition, got {}.'.format(type(value).__name__))
if value: # reject 0's
super(BasicComposition, self).__setitem__(key, value)
elif key in self:
del self[key]
辞書クラスを継承したコンポクラスを設定します。
ここでは、値をfloatもしくはintで受け取るのですが、roundし整数で保管します。
また、値が0の場合、そのキーを削除しています。
Pythonの場合、特殊メソッド(__getitem__, __setitem__, __delitem__等)を使用してコンテナー型(list/tuple/dict)を拡張することができます。
独習Python 515p
失敗 (Ruby)
def __setitem__(key, value)
if value.instance_of?(Float)
value = value.round
elsif value.instance_of?(Integer).!
raise PyteomicsError.new("Only integers allowed as values in Composition, got #{value.class}.")
end
if value != 0 # reject 0's
self[key] = value # 失敗
elsif self.include?(key)
self.delete(key)
end
end
def []=(...)
__setitem__(...)
end
これですと、[]=が無限ループとなってしまいます。
成功 (Ruby)
def __setitem__(key, value)
if value.instance_of?(Float)
value = value.round
elsif value.instance_of?(Integer).!
raise PyteomicsError.new("Only integers allowed as values in Composition, got #{value.class}.")
end
if value != 0 # reject 0's
self.merge!({key => value}) # 成功
elsif self.include?(key)
self.delete(key)
end
end
def []=(...)
__setitem__(...)
end
[]=を使用せずに、値を変更できればいいわけです。
もっといい書き方があるかもしれませんが。
メモ
- Python の 辞書クラスの拡張 を学習した
- 百里を行く者は九十里を半ばとす