From 79db6997bf31ff9d71320a1b6f68602f16dd4095 Mon Sep 17 00:00:00 2001 From: Philippe ENTZMANN Date: Wed, 12 Sep 2012 21:34:05 +0200 Subject: [PATCH] ENH: Series item access via attribute #1903 --- pandas/core/series.py | 16 ++++++++++++++++ pandas/tests/test_series.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/pandas/core/series.py b/pandas/core/series.py index 56688eae92242..d39dae9f7c86d 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -437,6 +437,22 @@ def ix(self): return self._ix + + def __getattr__(self, key): + # make sure there is something to look into + if self.index is not None: + # If attribute is in the Series index ... + if key in self.index: + # ... return item as an attribute + return self[key] + else: + # ... raise the usual exception + raise AttributeError("'Series' object has no attribute '%s'" % key) + else: + # ... raise the usual exception + raise AttributeError("'Series' object has no attribute '%s'" % key) + + def __getitem__(self, key): try: return self.index.get_value(self, key) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 5f6245f62f187..fb615526e67e9 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -4,6 +4,7 @@ import os import operator import unittest +import types import nose @@ -3133,6 +3134,36 @@ def test_unique_data_ownership(self): Series(Series(["a","c","b"]).unique()).sort() + def test_dot_notation_items_access(self): + ''' + cf #1903 + ''' + s = Series({'a' : 11, 'b' : 12, 'c' : 13, + 'append' : 14, 'T' : 15, + '100' : 16, '*' : 17}) + + # check dot notation / getattr() + self.assert_(s.a == getattr(s, 'a') == s['a'] == 11) + self.assert_(s.b == getattr(s, 'b') == s['b'] == 12) + self.assert_(s.c == getattr(s, 'c') == s['c'] == 13) + + # check getattr() for special keys (no dot notation) + self.assert_(getattr(s, '100') == s['100'] == 16) + self.assert_(getattr(s, '*') == s['*'] == 17) + + # check AttributeError on non-existing series keys + self.assertRaises(AttributeError, getattr, s, 'aaa') + self.assertRaises(AttributeError, getattr, s, 'other_key') + + # Existing methods/property should overwrite attribute dot notation + self.assert_(isinstance(s.append, types.MethodType)) + self.assert_(isinstance(s.T, Series)) + + # Masked attributes are still available via dict notation + self.assert_(s['append'] == 14) + self.assert_(s['T'] == 15) + + if __name__ == '__main__': nose.runmodule(argv=[__file__,'-vvs','-x','--pdb', '--pdb-failure'], exit=False)