はじめに
移植やってます。
( 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 の 辞書クラスの拡張 を学習した
- 百里を行く者は九十里を半ばとす