Originally, this question was "deepcopy a string in python" 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.
But first, part of original content: Deep copies of strings return the exact same string:
import copy
_1= "str"
_2 = copy.deepcopy(_str)
_1 is _2 # True
Novel content:
The questions are inline with the code. Basically, I am decorating a TestClass
with a decorator that is going to generate standardized 'appender' methods on the class for every attribute inserted in TestClass.channels
. 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 TestClass.channels
defined:
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'<some {ch}/{ch_type}> 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({"col1": [1, 2, 3], "col2": list("abc")}))
# TypeError: `text` only accepts values of `<class 'str'>` type, but found <class 'pandas.core.frame.DataFrame'>
test_inst.append_dataframe("A minimal trimmed example") # NOTE THE WRONG 'APPENDER'
test_inst.append_text("of the original implementation")
print(test_inst.data)
# Out {'text': ['A minimal trimmed example', 'of the original implementation']}
Be my guest to propose a better title. I am out of good ideas for a short, but informative title for this case.
(Windows 10, python 3.8 from an anaconda env)