Search code examples
python-3.xclassclass-variables

Class variable refuses to work via "self" but works with class name (Python)


I have a simple class and a class variable inside this class:

class QuotesToScrape:

    authors_list = []

    def __init__:

There is a line of code in a method inside this class (method is called from init):

def gather_authors_list(self):
    self.authors_list = some_value

This line does not work, variable authors_list still empty. But if I change "self" to class name it works just fine:

def gather_authors_list(self):
    QuotesToScrape.authors_list = some_value

No decorators used. I feel here is some importand trick I need to understand to prevent me from serious problems in future.

Added later. Important part: I have another class variable, "quotes", and it works just fine. Here is nearly full fragment of my code. Class variable "quotes" ok, class variable "authors_list" not ok.

class QuotesToScrape:

    quotes = []         
    authors_list = []   

    def __init__(self):
        for page_number in range(1, 501):
            page_url = self.make_page_url(page_number)
            soup = self.get_soup(page_url)
            if self.out_of_quotes(soup):
                break
            quote_blocks = self.parse_quotes(soup)
            for quote_block in quote_blocks:self.quotes
                quote = self.extract_quote(quote_block)
                self.quotes.append(quote)
        self.gather_authors_list()

...

    def gather_authors_list(self):
        authors = list(set([quote.get('Author') for quote in self.quotes]))
        if 'Alexandre Dumas fils' in authors:
            duma_index = authors.index('Alexandre Dumas fils')
            authors[duma_index] = 'Alexandre (fils) Dumas'
        self.authors_list = sorted(authors, key = lambda x: x.split(" ")[-1])

Added later. Problem solved. Changed last line to match directions from comments. This solved my problem, now method does not creates new variable, but uses existing empty class variable:

self.authors_list.extend(sorted(authors, key = lambda x: x.split(" ")[-1]))

Solution

  • Edited after edition in question: when you say self.authors_list = ... the class variable is not getting updated, instead a new object variable gets created, and it's available only to that class instance. In the case of quotes, you are doing any assignment, and instead, you do an append which gets reflected in the class variable quotes.

    When you did QuotesToScrape.authors_list instead, you changed the class variable, and this get's reflected in other object instances you create afterwards.

    Try understand your case with this example:

    class Yes:
        a = 1
        def __init__(self):
            pass
    
        def yes(self):
            if Yes.a==1:
                print "Yes"
            else:
                print "No, but yes"
    
    class No(Yes):
    
        def no(self):
            if Yes.a==1:
                print "No"
            else:
                print "Yes, but no"
            Yes.a-=1 #Note this line
    
    Yes().yes()
    No().no()
    Yes().yes()
    No().no()
    

    The answer of this is:

    Yes().yes()
    No().no()
    Yes().yes()
    No().no()
    

    I hope going through this example would aid in understanding your knowledge of class variables. Let me know if you have any doubt. :)