0

After running the code below, I expect that folders[0] has 1 File and folders[1] has 0 Files. Why is the code instead inserting the File into both Folders?

Code:

class Folder(object):
    # __init__
    def __init__(self):
        pass

    list_of_files = []


class File(object):
    # __init__
    def __init__(self):
        pass

    def insert_into_folder(self, folder):
        folder.list_of_files.append(self)


def main():
    folders = []
    folders.append(Folder())
    folders.append(Folder())

    f = File()
    f.insert_into_folder(folders[0])

    for folder in folders:
        print("Folder {:d} has {:d} file(s)".format(folders.index(folder), len(folder.list_of_files)))


if __name__ == "__main__":
    main()

Output:

Folder 0 has 1 file(s)
Folder 1 has 1 file(s)

Process finished with exit code 0
LarrySnyder610
  • 2,277
  • 12
  • 24

4 Answers4

1

list_of_files is a class variable and not an instance variable, meaning that all Folder's have the same list_of_files. Fix by changing this to an instance variable.

shuttle87
  • 15,466
  • 11
  • 77
  • 106
1

As one of the comment says :All folders are sharing a single list_of_files among themselves.

Therefore, in your case you want every folder to have his own list, therefore you need to do something like this:

class Folder(object):
    # __init__
    def __init__(self):
        self.list_of_files = []


class File(object):
    # __init__
    def __init__(self):
        pass

    def insert_into_folder(self, folder):
        folder.list_of_files.append(self)


def main():
    folders = []
    folders.append(Folder())
    folders.append(Folder())

    f = File()
    f.insert_into_folder(folders[0])

    for folder in folders:
        print("Folder {:d} has {:d} file(s)".format(folders.index(folder), len(folder.list_of_files)))


if __name__ == "__main__":
    main()

Output

Folder 0 has 1 file(s)
Folder 1 has 0 file(s)

By adding self.list_of_files = [], you're actually saying everytime I make an instance of Folder, add a list_of_files to this instance.

scharette
  • 9,437
  • 8
  • 33
  • 67
  • So does that mean all (instance) attributes of a class should be initialized in `__init__` rather than in the body of the class definition? – LarrySnyder610 Oct 28 '17 at 02:04
1

As Patrick pointed out, the way you have Folder defined, list_of_files is a class variable, meaning it is "global" to the class and there is only one copy of it, shared amongst all instances of the class.

If you want each Folder to have its own file list, define Folder like this:

class Folder(object):
    def __init__(self):
        self.list_of_files = []
John Gordon
  • 29,573
  • 7
  • 33
  • 58
1

You need an instance variable, not a class variable.

class Folder(object):
    # __init__
    def __init__(self):
        self.list_of_files = []
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245