开发者

Can I create object names from a text file in Python 2.7?

I'm working on a game project. I've created an object, Star(Object). I want to assign the name of the variables, dynamically, from a text file.

If I have a text file with:

Sol
Centauri
Vega

I want the program to create the Star(Object) with variable names from the text file. I want the process automated, because I'm looking to create hundreds of stars. I could write the code out by hand:

Sol = Star(Sol)
Centauri = Star(Centauri)
Vega = Star(Vega)

But isn't there a way to automate this?

Essentially, what I eventually want is a tuple with the list of stars, as their own objects. Then, when I am doing game maintenance, I can just iterate o开发者_开发百科ver all the objects in the tuple.


The name of a star should not be the name of the variable. Variable names should reflect the context in which the variable is used, e.g. destinationStar or homeStar.

A star's name should be a property of the Star object, accessed via Star.name:

class Star(object):
    """Keeps track of a star."""

    def __init__(self, starName):
        self.name = starName

    # other methods...

def read_stars(filename):
   # oversimplified:
   stars = {}
   starfile = open(filename, "r")
   for line in starfile:
      words = line.split()
      if len(words) == 2 and words[0] == 'star':
          name = words[1]
          stars[name] = Star(name)
   return stars

By storing in a dictionary, you can search for a particular Star with stars[name] or iterate over all the stars with for s in stars.values(), for example.


I want to assign the name of the variables, dynamically This is a very good indication that your design is completely wrong.

It's hard to know exactly what your design is, but I'm going to guess you want to use a dictionary instead.


class BadStar(Exception): pass

class Star(object):
    def __init__(self, name, mass, mag, color, x, y, z):
        self.name = name
        self.mass = float(mass)
        self.mag = float(mag)
        self.color = color
        self.pos = (float(x),float(y),float(z))

    @classmethod
    def fromstr(cls, s):
        "Alternate constructor from string"
        stardata = [i.strip() for i in s.split(',')]
        if len(stardata)==7:
            return cls(*stardata)
        else:
            raise BadStar("wrong number of arguments in string constructor")

    def __str__(self):
        x,y,z = self.pos
        return "{0} is at ({1}, {2}, {3})".format(self.name, x, y, z)

class StarIndex(dict):
    def load(self, fname):
        "Load stars from text file"
        with open(fname, "r") as f:
            for line in f:
                line = line.split('#')[0]   # discard comments
                line = line.strip()         # kill excess whitespace
                if len(line):               # anything left?
                    try:
                        star = Star.fromstr(line)
                        self[star.name] = star
                    except BadStar:
                        pass                # discard lines that don't parse
        return self

and some sample data:

# Name,           Mass, Absolute Magnitude, Color,     x,      y,      z
#
# Mass is kg
# Color is rgb hex
# x, y, z are lightyears from earth, with +x to galactic center and +z to galactic north
Sol,              2.0e30, 4.67,             0xff88ee,  0.0,    0.0,    0.0
Alpha Centauri A, 2.2e30, 4.35,             0xfff5f1, -1.676, -1.360, -3.835  

then you can load your file like:

s = StarIndex().load("stars.txt")

and

print s["Sol"]

results in

Sol is at (0.0, 0.0, 0.0)


Your question isn't clear. It's clouded by the fact that you're using syntax 'Star(Centauri)', which, in Python, means that you want to create a class called 'Star' that inherits from Centauri. I think what you want is probably a factory object that creates different stars, but then you don't say anything about how the stars might differ. Presumably, the difference is location, but you don't say how that's being handled either.

Best bet, based on guesses, might be to put your star configurations in a YAML file and use pyYAML to load it, which returns a Python data structure ready to go for you.


def makeStar(starName):
    globals()[starName] = Star(globals()[starName])
makeStar("Sol")

is the same as

Sol = Star(Sol)

except "Sol" can be replaced with any string (eg the values read in from that file).

Also, you may want to rethink making these global variables - it prevents you from being able to iterate through all the stars, should you need to, and could possibly cause naming conflicts. If you want these to be in a dictionary, then just replace "globals()" with the name of your dictionary.


You probably should use a dictionary for that. It is possible to create dinamic variable names, but it would make no sense, since to access then you would need an indirect reference anyway.

stars = {}
with open("stars.txt") as stars_file:
    for star_name in stars_file:
        star_name = star_name.strip()
        stars[star_name] = Star(star_name)


You can use the types module to create class objects at the run time:

import types

def make_class(name):
    cls = types.ClassType(name, (), {})
    return cls

cls = make_class("Star")
obj = cls()

In the above example, cls becomes your class Star

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜