Могу ли я создавать имена объектов из текстового файла в Python 2.7? - PullRequest
1 голос
/ 02 января 2011

Я работаю над игровым проектом. Я создал объект, Star (Объект). Я хочу назначить имя переменной динамически из текстового файла.

Если у меня есть текстовый файл с:

Sol
Centauri
Vega

Я хочу, чтобы программа создала звезду (объект) с именами переменных из текстового файла. Я хочу, чтобы процесс был автоматизирован, потому что я хочу создать сотни звезд. Я мог бы написать код вручную:

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

Но разве нет способа автоматизировать это?

По сути, я в конечном итоге хочу получить кортеж со списком звезд в качестве своих собственных объектов. Затем, когда я занимаюсь обслуживанием игры, я могу просто перебрать все объекты в кортеже.

Ответы [ 7 ]

4 голосов
/ 02 января 2011

Имя звезды не должно быть именем переменной.Имена переменных должны отражать контекст, в котором используется переменная, например, destinationStar или homeStar.

Имя звезды должно быть свойством объекта Star, доступ к которому осуществляется через 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

Сохраняя в словаре, вы можете искать определенный Star с помощью stars[name] или перебирать все звезды с помощью for s in stars.values(), например.

1 голос
/ 02 января 2011
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

и некоторые примеры данных:

# 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  

, затем вы можете загрузить свой файл следующим образом:

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

и

print s["Sol"]

приводит к

Sol is at (0.0, 0.0, 0.0)
1 голос
/ 02 января 2011

I want to assign the name of the variables, dynamically Это очень хороший признак того, что ваш дизайн совершенно неправильный.

Трудно точно знать, каков ваш дизайн, но я собираюсь догадаться, что вы хотите использовать словарь вместо этого.

0 голосов
/ 06 декабря 2011

Вы, вероятно, должны использовать словарь для этого.Можно создавать имена динамических переменных, но это не имеет смысла, поскольку для доступа в любом случае вам потребуется косвенная ссылка.

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)
0 голосов
/ 02 января 2011
def makeStar(starName):
    globals()[starName] = Star(globals()[starName])
makeStar("Sol")

совпадает с

Sol = Star(Sol)

кроме "Sol" можно заменить любой строкой (например, значения, считанные из этого файла).

Кроме того, вы, возможно, захотите переосмыслить создание этих глобальных переменных - это лишает вас возможности перебирать все звезды, если вам это необходимо, и может привести к конфликтам имен. Если вы хотите, чтобы они были в словаре, просто замените «globals ()» на имя вашего словаря.

0 голосов
/ 02 января 2011

Вы можете использовать модуль типов для создания объектов класса во время выполнения:

import types

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

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

В приведенном выше примере cls становится вашим class Star

0 голосов
/ 02 января 2011

Ваш вопрос не ясен. Это омрачено тем фактом, что вы используете синтаксис «Звезда (Центавра)», что в Python означает, что вы хотите создать класс под названием «Звезда», который наследуется от Центавра. Я думаю, что вы хотите, вероятно, фабричный объект, который создает разные звезды, но тогда вы ничего не говорите о том, как звезды могут отличаться. Предположительно, разница в расположении, но вы также не говорите, как это обрабатывается.

Лучшая ставка, основанная на догадках, может заключаться в том, чтобы поместить ваши звездные конфигурации в файл YAML и использовать pyYAML , чтобы загрузить его, что возвращает готовую для вас структуру данных Python.

...