简体   繁体   中英

“self.data” usage in python

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.

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:

  1. You create a new instance of your class. At this point, Python knows nothing about self.data :

     lazy = Lazy() 
  2. You call it passing None :

     lazy(None) 
  3. 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, ie 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...

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

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

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.

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM