Ссылаясь на имена классов через строки? - PullRequest
1 голос
/ 09 августа 2010

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

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

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

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

Спасибо!

Что

Ответы [ 5 ]

11 голосов
/ 09 августа 2010

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

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

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

globals()[ "Laptop" ]

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

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

mapping = { "Laptop": Laptop, "Nettop": Laptop, ... }
mapping[ "Laptop" ]()
5 голосов
/ 09 августа 2010

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

obj = globals()[classname]()

где classname - строка

4 голосов
/ 09 августа 2010

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

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

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

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

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

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

1 голос
/ 09 августа 2010

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

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

Пример:

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)
0 голосов
/ 09 августа 2010

Не уверен насчет синтаксиса кода 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...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...