I made a class. I think that I create a member variable named "myTup" in the initializer/constructor. I try to make sure that I actually did create myTup by making the following call right at the very end of the initializer:
assert(hasattr(self, 'myTup'))
However, later, the interpreter says that my instance/object doesn't have a member variable named "myTup."
Where did myTup go? Come back to me... please Q_Q
The following script is only long due to all of the little debug statements. Without the debugging, it's actually quite short and simple.
Code:
import inspect
def lineno():
# Returns the current line number in our program.
return inspect.currentframe().f_back.f_lineno
class DemoClass:
def __init__(self, initial_data):
went_in = False # did not enter the if-elif-else block
if isinstance(initial_data, str):
print('line number:', lineno())
t = tuple(initial_data)
self = DemoClass(t)
went_in = True
elif isinstance(initial_data, DemoClass):
print('line number:', lineno())
self = initial_data
went_in = True
elif isinstance(initial_data, tuple):
print('line number:', lineno())
self.myTup = initial_data
went_in = True
else:
print('line number:', lineno())
went_in = True
assert(False)
assert(hasattr(self, 'myTup'))
print('line number:', lineno())
print('went_in:', went_in)
print('myTup:', self.myTup)
def __str__(self):
return "DemoClass" + str(self.myTup)
obj = DemoClass("s")
print(obj)
Output:
line number: 13
line number: 22
line number: 31
went_in: True
myTup: ('s',)
line number: 31
went_in: True
myTup: ('s',)
Traceback (most recent call last):
[... truncated / abridged ...]
File "E:/awesome_folder_name/missing_member_var.py", line 36, in __str__
return "DemoClass" + str(self.myTup)
AttributeError: 'DemoClass' object has no attribute 'myTup'
You can't replace the instance created in
__init__
. The following replaces only theself
reference in the__init__
method, not the previous instance thatself
was bound to:When
__init__
returns, theobj = DemoClass("s")
line still bound the first instance, not the one you created with your recursive call. That first instance has nomyTup
attribute.You'd have to call
self.__init__(t)
instead to operate on the same instance:This then calls
__init__
again, with the same instance bound, and thus will setmyTup
on the right object.Note that I'd avoid using recursion here. There is no need, just set a tuple in the different branches and then assign
myTup
at the end:If you must control what instance is returned when trying to create a new one with
DemoClass()
, then you can only do so with the__new__
method; it is responsible for producing the instance in the first place (after which the default implementation would call__init__
on that new instance).