Reputation: 791
Hello I have a question about attribute usage in Python. I learned that in function definition we can assign some new attributes for objects for example: self! However, when try to use that I got an error which is "... instance has no attribute 'data'
class Lazy:
def __call__(self, num):
if num is None:
return self.data
# It changes the current object in-place,
# by reassigning the self attribute.
else:
self.data += num
This is my little code. I'm very new at this. I couldn't figured out what is wrong. Thank you very much.
Upvotes: 3
Views: 15180
Reputation: 2857
I would like to point out that in your code:
class Lazy:
def __init__(self):
self.data = 0
def __call__(self, num):
if num is None:
return self.data
suppose if you call your instance like: lazy(some_value)
then your else branch will execute which evaluates to:
else:
self.data += num # self.data = self.data + num
but, there may be the case in which self.data may be undefined in that case too it will through the above error.
I agree with all the above answers but I needed to focus this corner case too.
enjoy!
Upvotes: 1
Reputation: 496
You can init the attribute in __init__()
method, or anywhere else (although __init__()
is the recommended place).
Try self.data
and initialize it if it doesn't exist.
class Lazy:
def __call__(self, num):
try:
self.data
except:
self.data = 0
if num is None:
return self.data
# It changes the current object in-place,
# by reassigning the self attribute.
else:
self.data += num
I hope it helps.
Upvotes: 1
Reputation: 15803
You are only assigning self.data
if num is None
, so it can happen that you try to access it before it has been assigned. To prevent this, you could initialize it in the constructor:
class Lazy:
def __init__(self):
self.data = 0
def __call__(self, num):
if num is None:
return self.data
else:
self.data += num
Here's what sequence of events causes your error:
You create a new instance of your class. At this point, Python knows nothing about self.data
:
lazy = Lazy()
You call it passing None
:
lazy(None)
Now, Python enters __call__
and because the if condition evaluates to True
it tries to return self.data
. Wait a minute... it still doesn't know what self.data
is... so it spits out an error.
In order to prevent this, you always have to assign your attributes before trying to do something with their values (for instance, returning them from a function). It doesn't have to be in the constructor: just before the first time Python tries to access the attribute. This is true for any variable, i.e. the following is impossible:
print(a) # How do you expect Python to know the value of a?
a = 5 # too late to assign it now...
Upvotes: 5
Reputation: 2477
In order to modify self.data
, you must first initialize the self.data
attribute by using the special __init__
method for classes.
From the official documentation:
object.__init__(self[, ...])
Called when the instance is created. The arguments are those passed to the class constructor expression.
So you could set self.data
to 0, then your __call__
method should work as written.
class Lazy:
def __init__(self):
self.data = 0
def __call__(self, num):
if num is None:
return self.data
else:
self.data += num
Upvotes: 1
Reputation: 99680
You are trying to reference self.data
however not initialized/declared it.
class Lazy:
def __init__(self, data=0):
self.data = data #You are initializing data to 0 or a user specified value
def __call__(self, num):
if num is None:
return self.data
# It changes the current object in-place,
# by reassigning the self attribute.
else:
self.data += num
Upvotes: 1