开发者

python : read a line, then instantiate a class named in the line

开发者 https://www.devze.com 2023-01-09 13:04 出处:网络
I\'m sorry if I wasn\'t clear enough in the title, don\'t hesitate to correct it if you find a better way to express that:

I'm sorry if I wasn't clear enough in the title, don't hesitate to correct it if you find a better way to express that:

I have a file where there are class names, i.e.:

classa
classb
classb
classc
classc
classc

Then I want to read it line by line and to dynamically create that class. I would do something like that in php:

while (!eof())
{
开发者_开发百科   $class=fread(..)
   $tab[] = new $class();
}

How would you do that in python (if it's possible)?

Thanks a lot!

Edit: after reading the answers, to be more precise on what I'm planning to do: I'm not planning to do such a simple stuff. It will be far more complex: I want a user who doesn't know programming to edit a simple text file, and to copy/paste some declarations and change their properties and to re-launch a kind of parser which will re-run a batch and show the result of complex operations. Simplified Example of a file:

car:(red,4_wheels,4_places)
bike:(blue,2_wheels,1_place)

Then the user will change it to:

car:(red,4_wheels,4_places)
car:(yellow,4_wheels,2_places)
bike:(blue,2_wheels,1_place)
bike:(green,2_wheels,2_places)

And then with python I'll read this file, create two instances of the class car, and two instances of the class bike. Thus a user who doesn't understand / know python will be able to edit the file without touching a line of code. I think this is the right way to go, if you have any other suggestions for this code, you're welcome!

Olivier Pons


Assuming your classes are already in scope (i.e. they're not in a separate module), you can refer to a class by its name very easily through the globals() dict. For example:

class Foo:
    pass

foo_cls = globals()['Foo']
foo = foo_cls()
# foo is now an instance of __main__.Foo


The other answers do what you asked, but I wanted to add a small measure of flexibility (and protection.) I would use a dictionary to map the line names to the class objects, so you're not letting the text file instantiate anything it wants. It has to be a class that you allow it to, in your code. This also makes it easier because you can change names on either side without trouble (and you could map multiple line-names to a single class name, if you wanted.)

classes = {'classa': classa, 'classb': classb}
cls = type(classes[line], (object,), {})  ## or whichever method to instantiate you prefer

But in general, it's not a very Pythonic thing to do, in my opinion.


As you are using YAML anyway, consider using PyYAML with the serialized classes deriving from the yaml.YAMLObject metaclass or registering your own represenenter.

From the documentation of PyYAML:

class Monster(yaml.YAMLObject):
    yaml_tag = u'!Monster'
    def __init__(self, name, hp, ac, attacks):
        self.name = name
        self.hp = hp
        self.ac = ac
        self.attacks = attacks
    def __repr__(self):
        return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
            self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)

print yaml.load("""
--- !Monster
name: Cave spider
hp: [2,6]    # 2d6
ac: 16
attacks: [BITE, HURT]
""")

prints Monster(name='Cave spider', hp=[2, 6], ac=16, attacks=['BITE', 'HURT'])

That way you can leave out many of the code you need for error handling (e.g. class is not present) and you also have system that is more robust against malicious configuration files. As an additional bonus, you are able to dump objects from your program into a YAML file.


Reading each line from the file is pretty easy:

with open(filename) as f:
    for line in f:

The first thing that comes to mind for class creation is the type function:

        cls = type(line, (object,), {})

This will create a new empty class which is a subclass of object and has a name given by the contents of the line.

I have to wonder why you're trying to do this, though. An empty class like that doesn't seem very useful in Python.


Assuming that all classes are declared in a module foo:

classname = sys.stdin.read().rstrip()
cls = getattr(foo, classname)()

To access classes in the same module, use the builtin globals() function.


This should be fairly easily possible using a dictionary of classes (not that this is not necessarily a restriction as each python namespace can be accessed as a dictionary so if you want these classes say to all be within a module or another class, just replace classes with the __dict__ attribute of the class or use globals as others have suggested):

classes = dict()
with open('filename') as f:
    for line in f:
        classes[line] = class()

(Implementation details may vary).

You may however want to look into using pickling instead as on the face of it, this approach seems flawed (it might work well in PHP though :-) ).

0

精彩评论

暂无评论...
验证码 换一张
取 消