計算済みの値があるので、インスタンスメソッドを実行せずに値を返したい。簡易メモ化。
計算済みならインスタンス変数にセット、それ以外はインスタンスメソッドを実行、という挙動を実装してみる。
python のデータの持ち方はハッシュだから、名前を確認すればインスタンス変数があるか確認できる。
ruby だとどうやるのかと思ったら、instance_variable_defined? というメソッドがあった。
class A
def a=(a)
@a = a
end
def a
@a
end
end
class B
def a=(a)
@a = a
end
def a
return @a if instance_variable_defined?(:@a)
"b"
end
end
require 'minitest/unit'
require 'minitest/autorun'
class ATest < MiniTest::Unit::TestCase
def test_undefined_instance_variable_is_nil
a = A.new
assert_equal nil, a.a
end
end
class BTest < MiniTest::Unit::TestCase
def test_undefined_instance_variable_is_constant
b = B.new
assert_equal "b", b.a
end
def test_gettable_instance_variable_after_set
b = B.new
b.a = "a"
assert_equal "a", b.a
end
end
`Run options: --seed 38869
# Running tests:
...
Finished tests in 0.001566s, 1915.7088 tests/s, 1915.7088 assertions/s.
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
名前が長いということは、使用を推奨されないということなのだろうか?
python は hasatter で何でもイケる。
import unittest
class A(object):
@property
def a(self):
return self._a
@a.setter
def a(self, a):
self._a = a
class B(object):
@property
def a(self):
if hasattr(self, "_a"):
return self._a
return "b"
@a.setter
def a(self, a):
self._a = a
class ATest(unittest.TestCase):
def test_undefined_instance_variable_is_error(self):
a = A()
self.assertRaises(AttributeError, lambda : a.a)
class BTest(unittest.TestCase):
def test_undefined_instance_variable_is_constant(self):
b = B()
self.assertEqual("b", b.a)
def test_gettable_instance_variable_after_set(self):
b = B()
b.a = "a"
self.assertEqual("a", b.a)
unittest.main()