title: A decorator performing automatic method generation on a class by looping: all methods seem to use the same exact inputs but shouldn't
body: <p>Originally, this question was &quot;deepcopy a string in python&quot; and I am keeping the essential parts of the discussion here for reference. Although I did solve the issue, I do not understand neither the origin of the issue nor how the solution differs from the wrong/not working implementation. I do want to understand this and took my time trimming the actual code into a minimal working example.</p>
  <p>But first, <strong>part of original content</strong>: Deep copies of strings return the exact same string:</p>
  <pre><code>import copy
  _1= &quot;str&quot;
  _2 = copy.deepcopy(_str)
  _1 is _2 # True
  </code></pre>
  <p><strong>Novel content</strong>:
  The questions are inline with the code. Basically, I am decorating a <code>TestClass</code> with a decorator that is going to generate standardized 'appender' methods on the class for every attribute inserted in <code>TestClass.channels</code>. Please note, I am not posting the question to discuss software architecture/implementation, but to actually understand the interstitials of Python relevant to the noted issue: why all 'appenders' generated will actually perform exactly the same work as that prepared for the last attribute of <code>TestClass.channels</code> defined:</p>
  <pre><code>import pandas as pd
  
  
  def standardize_appenders(kls):
      # Checks `kls` for `channels`, whether an appropriate pseudo implementation of 'appenders' is
      # available and actually implements the `appenders`: BESIDES AUTOMATION, I AM FORCING A STANDARD
      channels = getattr(kls, 'channels')
      chs = [o for o in dir(channels) if not o.startswith('_')]
      chs_type = [getattr(channels, o) for o in chs]
  
      for _ch, _ch_type in zip(chs, chs_type):  # ISSUE SOMEWHERE HERE
          ch = _ch
          ch_type = _ch_type
  
          # THE `def appender(self, value, ch=ch, ch_type=ch_type)` SIGNATURE SOLVES THE PROB BUT I DON'T UNDERSTAND WHY
          def appender(self, value):
              # nonlocal ch, ch_type
              if not isinstance(value, ch_type):
                  raise TypeError(f'`{ch}` only accepts values of `{ch_type}` type, but found {type(value)}')
              data: dict = getattr(self, 'data')  # let's not discuss the need for this knowledge please
              data_list = data.setdefault(ch, [])
              data_list.append(value)
              data.setdefault(ch, data_list)
  
          appender.__doc__ = f'&lt;some {ch}/{ch_type}&gt; specific docstring'
  
          setattr(kls, 'append_' + ch, appender)  # ALL APPENDERS OF `kls` WILL DO ESSENTIALLY THE WORK DEFINED LAST
  
      return kls
  
  
  @standardize_appenders
  class TestClass:
      class channels:
          dataframe = pd.DataFrame
          text = str
  
      def __init__(self):
          self.data = {}
  
  
  if __name__ == '__main__':
      test_inst = TestClass()
      # test_inst.append_dataframe(pd.DataFrame({&quot;col1&quot;: [1, 2, 3], &quot;col2&quot;: list(&quot;abc&quot;)}))
      # TypeError: `text` only accepts values of `&lt;class 'str'&gt;` type, but found &lt;class 'pandas.core.frame.DataFrame'&gt;
      test_inst.append_dataframe(&quot;A minimal trimmed example&quot;)  # NOTE THE WRONG 'APPENDER'
      test_inst.append_text(&quot;of the original implementation&quot;)
      print(test_inst.data)
      # Out {'text': ['A minimal trimmed example', 'of the original implementation']}
  </code></pre>
  <p>Be my guest to propose a better title. I am out of good ideas for a short, but informative title for this case.</p>
  <p>(Windows 10, python 3.8 from an anaconda env)</p>