Мне нужно проанализировать некоторый текстовый файл, создать объекты для различных объектов, встречающихся в тексте, и поместить их в некоторую структуру данных (например, список) для дальнейшей обработки. Пример текста:

laptop
 17" dell, weight: 12 lb
desktop
 24" hp

Я заранее знаю, какие объекты могут существовать в тексте, и какие атрибуты они должны иметь. В этом примере я уже определил бы классы ноутбука и рабочего стола (вероятно, подклассы класса компьютер). Синтаксическому анализатору нужно будет просто создать объекты «ноутбук» («dell», 17, 12) и «декстоп» («hp», 24).

Если я пойду по этому пути, мне нужно будет извлечь имена классов из строк и создать объекты этих классов. Это Pythonic способ делать вещи? Если да, то какой подход лучше (использовать Python 3.1)? Если нет, что я должен делать вместо этого?

Благодарность!

Какая

1
max 9 Авг 2010 в 14:23

5 ответов

Лучший ответ

Если классы определены в computers.py, скажем, вы можете сделать

import computers
getattr( computers, "Laptop" )( <params> )

Создать экземпляр computers.Laptop. Если они определены в том же файле, в котором вы запускаете код (так что они являются глобальными переменными), вы можете сделать

globals()[ "Laptop" ]

Но это менее элегантно; было бы лучше поместить их в отдельную сферу.

В качестве альтернативы, если вам нужно более мощное отображение (скажем, вы хотите, чтобы "Nettop", "Lapbook" и "Laptop" все создавали экземпляр Laptop), вы можете сохранить отображение строк в соответствующем конструкторе и использовать это:

mapping = { "Laptop": Laptop, "Nettop": Laptop, ... }
mapping[ "Laptop" ]()
11
Katriel 9 Авг 2010 в 10:31

Вы можете создавать экземпляры класса по его имени, используя следующий код

obj = globals()[classname]()

Где classname строка

5
Nikolaus Gradwohl 9 Авг 2010 в 10:28

Я думаю, что метод, основанный на проверке, потенциально может быть достаточно хрупким и устойчивым к изменениям. Что если вы хотите использовать классы из других модулей?

Почему не объектная фабрика? Это может быть простая функция или класс.

Примере:

class ComputerFactory:

   def __init__(self):
      self._classes = {}

   def register(moniker, creator):
      """Moniker is a name for the class.
      Creator is a callable that creates the object 
      for the moniker.
      """
      self._classes[moniker] = creator

   def create(moniker, *args, **kwargs):
      return self._classes[moniker](*args, **kwargs)

# Example usage
fac = ComputerFactory()
# Register constructor
fac.register("laptop", Laptop) # Laptop class is also a callable (the constructor)
# Register construction proxy
def sony_laptop_builder(make):
   return Laptop("Sony")
fac.register("laptop", sony_laptop_builder)
1
Skurmedel 9 Авг 2010 в 10:48

Не уверен насчет синтаксиса кода Python, но это то, что вы хотите?

for item in parsedString:
    if item == "laptop":
        laptops.add(laptop()) #laptops is a list of laptops you 
                              #have encountered so far in your list
    # add the next elements to your laptop instance

    if item == "desktop":
    # code for desktop...
0
Katriel 9 Авг 2010 в 11:10

Технически, то, что вы просите (или, по крайней мере, то, как все это интерпретируют), просто не очень хорошая практика, особенно если вы можете получать информацию из ненадежного источника (помните, любой источник , кроме вас <) / em> обычно считается недоверенным!). Вы должны явно занести в белый список эти вещи, потому что кто-то может инициировать выполнение функции или создание объекта, для которого вы не предназначались свойства, которые вам действительно не нужны ...

Вместо этого вы можете сделать что-то вроде этого (это, конечно, дико неполно, но должно дать вам общее представление):

class Laptop(object):
    pass
class Desktop(object):
    pass

possible_classes = {
    "laptop": Laptop,
    "desktop": Desktop,
}

new_object = possible_classes[identifier_string](propA, propB, propC, ...)

Затем просто добавьте отображение для каждого нового типа объекта в dict возможные_классы.

4
Nicholas Knight 9 Авг 2010 в 10:38