Search code examples
python-3.xclassoopglobal-variables

How to declare a global variable set to a method in __init__ in Python?


I am new to object-oriented programming and I have some trouble with declaring global variables that are set to a method inside a class. I declared them in the __init__ method (I want them to be inside the class, not outside) with self.censored_transcript = self.apply_filter(), and within this file, everything works fine. But when I import the class in a different .py file and instantiate the Profanity class, the following error occurs: UnboundLocalError: local variable 'censored_transcript' referenced before assignment. I have done quite some research on this topic but can't find anything that fits my case. The global statement does not work. Can anyone please let me know how I can fix this? Thank you very much in advance!

File 1 (file to be imported), called profanity_filter.py:

from better_profanity import profanity


class Profanity(object):

    def __init__(self, transcript_filename, wordlist_filename):
        self.__transcript_filename = transcript_filename
        self.__wordlist_filename = wordlist_filename

        self.__transcript = self.__load_transcript()
        self.censored_transcript = self.apply_filter()

    def __load_transcript(self):
        f = open(self.__transcript_filename, "r")
        file = f.read()
        f.close()

        return file

    def apply_filter(self):
        if __name__ == "__main__":
            profanity.load_censor_words_from_file(self.__wordlist_filename)
            censored_transcript = profanity.censor(self.__transcript)

        return censored_transcript

File 2 (test file):

from profanity_filter import Profanity


# Instantiate the Profanity class:
p = Profanity("sample_transcript.txt", "profanity_wordlist.txt")


# Apply the profanity filter.
censored_transcript = p.apply_filter()
print(censored_transcript)

Solution

  • You can use self.censored_transcript in all places inside your class - self refers to current object of class. Each created object of your class will store self self set of variables available.

    censored_transcript without self treated as regular local variable which will be newly created for each call of method.

    Error cause: When method def apply_filter(self) gets called from outer .py file, if __name__ == "__main__" check will be false and local variable censored_transcript will not be created inside this method. So, return censored_transcript tries to return local variable with unassigned value and fails.

    Solution 1: in apply_filter(self) you can use object's censored_transcript, not local, to save result. Just append self. before it. And you do not need to return something from this method:

    from better_profanity import profanity
    
    
    class Profanity(object):
    
        def __init__(self, transcript_filename, wordlist_filename):
            self.__transcript_filename = transcript_filename
            self.__wordlist_filename = wordlist_filename
    
            self.__transcript = self.__load_transcript()
            self.apply_filter()  # changed
    
        def __load_transcript(self):
            f = open(self.__transcript_filename, "r")
            file = f.read()
            f.close()
    
            return file
    
        # changed
        def apply_filter(self):
            profanity.load_censor_words_from_file(self.__wordlist_filename)
            self.censored_transcript = profanity.censor(self.__transcript)
    

    Solution 2: use a local variable, but assign value to it without if. Or even omit this local variable:

    from better_profanity import profanity
    
    
    class Profanity(object):
    
        def __init__(self, transcript_filename, wordlist_filename):
            self.__transcript_filename = transcript_filename
            self.__wordlist_filename = wordlist_filename
    
            self.__transcript = self.__load_transcript()
            self.censored_transcript = self.apply_filter()
    
        def __load_transcript(self):
            f = open(self.__transcript_filename, "r")
            file = f.read()
            f.close()
    
            return file
    
        # changed
        def apply_filter(self):
            profanity.load_censor_words_from_file(self.__wordlist_filename)
            return profanity.censor(self.__transcript)