James Kolber James Kolber - 3 months ago 26
Python Question

Auto creating instances of class

I'm trying to create instances of a class by loading a textfile and using some strings from that as input.

This is supposed to spit out all the scene headers from a film manuscript and create an instance of a Scene class for every time it reads a scene header that is characterized by starting with either INT or EXT.

While it does find all the scenes correctly, I am having trouble creating the actual instances.

How do I make instances of Class in the create function, and then print them out ?

class Scene(object):
def __init__(self, name, isint, isday):
self.name = name
self.isint = bool(isint)
self.isday = bool(isday)

def create(self):
with open('output.txt', 'r') as searchfile:
for line in searchfile:
if 'INT' in line or 'EXT' in line:
return Scene()
if line.startswith(INT):
Scene.isint == True
if line.endswith('NAT\n'):
Scene.isday == False

def __repr__(self):
print(self)

Answer

Your function shouldn't be a method of Scene, since it doesn't actually do anything but create a bunch of objects. You can use generators to emit your Scene instances as you parse the file:

def read_scenes(filename):
    with open(filename, 'r') as handle:
        scene = Scene(None, None, None)

        for line in handle:
            if line.startswith('INT'):
                scene.isint = True

            if line.endswith('NAT\n'):
                scene.isday = False

            if 'INT' in line or 'EXT' in line:
                # Spit out the current scene
                yield scene

                # Create a new one
                scene = Scene(None, None, None)

for scene in read_scenes('output.txt'):
    print(scene)

Original answer

Your create function is an instance method, so it requires you create an instance of your class first and then call the create method. This is kind of backwards if you think about it, since your create method should not require an instance of a class, since it should be the one creating the instance.

The solution is to make your create method a class method. Instance methods take in an instance of your class as their first argument, while class methods take in the class itself, letting you create instance of your class using different functions.

class Scene(object):
    def __init__(self, name, isint, isday):
        self.name = name
        self.isint = bool(isint)
        self.isday = bool(isday)

    @classmethod
    def from_file(cls, filename, name):
        isint = None
        isday = None

        with open(filename, 'r') as searchfile:
             for line in searchfile:
                if 'INT' in line or 'EXT' in line:
                    return cls(name, isint, isday)

                if line.startswith(INT):
                    isint = True

                if line.endswith('NAT\n'):
                    isday = False

Since the function is a class method, you don't need an instance of your Scene class to call it:

scene = Scene.from_file('output.txt', 'The Name')

It's equivalent to doing something like:

name, isint, isday = parse_scene_file('output.txt')
scene = Scene(name, isint, isday)