2015-01-05 6 views
1

Целью является создание класса с использованием метода __init__, который позволит создавать объекты, которые будут инициализированы определенным словарем.Инициализировать объект, построенный из класса с помощью определенного словаря

Детали:

файловое mydicts.py представляет собой набор различных словарей. Объект, построенный из класса, который я намерен создать, будет инициализирован одним из словарей от mydicts.py.

mydicts.py пример:

dict1 = {k1:v1, k2:v2,...,kn:vn} 
dict2 = {k1:v1, k2:v2,...,km:vm} 
etc. 

Мои попытки:

class Example(dict): 
    def __init__(self, dictx): 
     self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx) 

Результаты:

e = Example('dict1') 
print e 
{}  # <- got empty dictionary. Want {k1:v1, k2:v2,...,kn:vn} 

Цель состоит в том, чтобы создавать объекты, такие, что:

a = Example(dict1) 
print a 
# {k1:v1, k2:v2,...,kn:vn} 

b = Example(dict2) 
print b 
# {k1:v1, k2:v2,...,km:vm} 
+1

для печати информации о каком-либо объекте вам нужно определить '__str__' метод внутри класса. попробуйте напечатать self.dictx в этом методе, он будет неявным образом вызван, когда вы напечатаете экземпляр этого класса – ZdaR

+0

. Я должен принять решение @ iCodez, поскольку он был более подробным, но это вокруг той же идеи, что и вы предложили. – flamenco

ответ

2

Поскольку вы не определили пользовательский __str__ method для своего класса, print вызывает метод __str__ родительского класса dict. Более того, это приводит к тому, что Python печатает пустой словарь, созданный родительским классом, в dict.__new__ вместо словаря, который вы сохранили в self.dictx.

Поскольку ваш класс наследуется от dict, вы должны передать словарь, возвращаемый getattr, методу __init__ родительского класса. Вы можете использовать super для этого:

class Example(dict): 
    def __init__(self, dictx): 
     dct = getattr(__import__("__main__", fromlist=['m']), dictx) 
     super(Example, self).__init__(dct) 

Это будет инициализировать родительский класс с данными, полученными из dct. Другими словами, пустой словарь был заменен на словарь, возвращаемый getattr. Так что, когда print называет __str__ метод родителя, правильный выход будет дан:

>>> dict1 = {'k1':'v1', 'k2':'v2', 'kn':'vn'} 
>>> class Example(dict): 
...  def __init__(self, dictx): 
...   dct = getattr(__import__("__main__", fromlist=['m']), dictx) 
...   super(Example, self).__init__(dct) 
... 
>>> e = Example('dict1') 
>>> print e 
{'k2': 'v2', 'k1': 'v1', 'kn': 'vn'} 
>>> 

Альтернативным решением было бы определить метод пользовательского __str__ для вашего класса, который возвращает self.dictx в виде строки:

class Example(dict): 
    def __init__(self, dictx): 
     self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx) 
    def __str__(self): 
     return str(self.dictx) 

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

+0

Пятно на! Теперь ясно. Ура! – flamenco

1

Я думаю, что вы делаете это намного сложнее, чем нужно. Отмечая the manual says:

Прямое использование __import__() редко, за исключением тех случаев, когда вы хотите импортировать модуль, имя которого известно только во время выполнения.

Но вы знаете имя модуля во время загрузки, ваше определение данных имеет слишком много имен переменных.Гораздо понятнее будет my_dicts.py:

my_dicts = [ 
    {k1:v1, k2:v2,...,kn:vn}, 
    {k1:v1, k2:v2,...,km:vm}, 
    … 
] 

и example.py:

import my_dicts 

class Example(dict): 
    def __init__(self, n): 
     """Returns an Example instance loaded with the nth element 
      of my_dict.""" 
     super(Example, self).__init__(my_dicts.my_dicts[n]) 
+0

На самом деле, имя - это словарь, известный во время исполнения, и словари названы. Тем не менее, приятное решение! – flamenco

+0

Затем я возвращаюсь к критерию CS101, что всякий раз, когда у вас есть набор переменных формы {d1, d2, ... d10000}, у вас на самом деле есть список (массив), который скрыт. Использование псевдо-списка сильно ограничивает гибкость и расширяемость данных, поскольку, если вам нужно d10001, код необходимо изменить, чтобы поддерживать его вместо простых данных. Кроме того, метод '__import__' является загадочным и отправит следующего читателя в руководство и все еще задается вопросом, что означает' fromlist = 'в контексте. – msw

Смежные вопросы