title: Best Practices to add custom attributes to pandas Dataframe
body: <p>I am building a <code>Table</code> class to make it easy to retrieve data from a database, manipulate it arbitrarily in memory, then save it back. Ideally, these tables work for the python interpreter and normal code. &quot;Work&quot; means I can use all standard pandas <code>Dataframe</code> features, as well as all custom features from the <code>Table</code> class.</p>
  <p>Generally, the tables contain data I use for academic research or personal interest. So, the user-base is currently just me, but for portability I'm trying to write as generically as possible.</p>
  <p>I have seen several threads (<a href="https://stackoverflow.com/questions/54605964/composition-versus-subclass-for-pandas-dataframe">example 1</a>, <a href="https://stackoverflow.com/questions/22155951/how-can-i-subclass-a-pandas-dataframe">example 2</a>) discussing whether to subclass <code>DataFrame</code>, or use composition. After trying to walk through <a href="https://pandas.pydata.org/pandas-docs/stable/development/extending.html#extending-subclassing-pandas" rel="nofollow noreferrer">pandas's subclassing guide</a> I decided to go for composition because pandas itself says this is easier.</p>
  <p>The problem is, I want to be able to call any <code>Dataframe</code> function, property, or attribute on a <code>Table</code>, but I to do so, I have to keep track of any attribute I code into the <code>Table</code> class. See below, points of interest are <code>metadata</code> and <code>__getattr__</code>, everything else is meant to be illustrative.</p>
  <pre><code>class Table(object):
      metadata = ['db', 'data', 'name', 'clean', 'refresh', 'save']
  
      def __getattr__(self, name):
          if name not in Table.metadata:
              return getattr(self.data, name) #self.data is the Dataframe
      
      def __init__(self, db, name):
          #set up Table specific values
  
      def refresh(self):
          #undo all changes since last save
  
      etc...
  </code></pre>
  <p>Obviously, having to explicitly specify the <code>Table</code> attributes versus the <code>Dataframe</code> ones is not ideal (though--to my understanding--this is how pandas implements column names as attributes). I could write out <code>tablename.data.foo</code>, but I find that unintuitive and non-pythonic. Is there a better way to achieve the same functionality?</p>