/ lib / pandas / _libs / properties.pyx
properties.pyx
 1  from cpython.dict cimport (
 2      PyDict_Contains,
 3      PyDict_GetItem,
 4      PyDict_SetItem,
 5  )
 6  from cython cimport Py_ssize_t
 7  
 8  
 9  cdef class CachedProperty:
10  
11      cdef readonly:
12          object fget, name, __doc__
13  
14      def __init__(self, fget):
15          self.fget = fget
16          self.name = fget.__name__
17          self.__doc__ = getattr(fget, '__doc__', None)
18  
19      def __get__(self, obj, typ):
20          if obj is None:
21              # accessed on the class, not the instance
22              return self
23  
24          # Get the cache or set a default one if needed
25          cache = getattr(obj, '_cache', None)
26          if cache is None:
27              try:
28                  cache = obj._cache = {}
29              except (AttributeError):
30                  return self
31  
32          if PyDict_Contains(cache, self.name):
33              # not necessary to Py_INCREF
34              val = <object>PyDict_GetItem(cache, self.name)
35          else:
36              val = self.fget(obj)
37              PyDict_SetItem(cache, self.name, val)
38          return val
39  
40      def __set__(self, obj, value):
41          raise AttributeError("Can't set attribute")
42  
43  
44  cache_readonly = CachedProperty
45  
46  
47  cdef class AxisProperty:
48  
49      cdef readonly:
50          Py_ssize_t axis
51          object __doc__
52  
53      def __init__(self, axis=0, doc=""):
54          self.axis = axis
55          self.__doc__ = doc
56  
57      def __get__(self, obj, type):
58          cdef:
59              list axes
60  
61          if obj is None:
62              # Only instances have _mgr, not classes
63              return self
64          else:
65              axes = obj._mgr.axes
66          return axes[self.axis]
67  
68      def __set__(self, obj, value):
69          obj._set_axis(self.axis, value)