2014-09-25 1 views
0

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

class test(object): 
def __init__(self, name, number_array): 
    self.name = name 
    self.number_array = number_array 
    self.graph= barChart(number_array) 

sample_obj = test('test_object', [(x1,y1), (x2,y2)etc.]) 

, но так, что {sample_obj: another_object} будет выглядеть {'test_object': another_object}

в то же время сделать что-то подобное можно:

for key, val in sample_dict.items(): print(key.name, key.graph) 

, а также:

>>> sample_dict['test_object'] 
another_object 
+0

В настоящее время нет способа предоставить такие ключевые псевдонимы, чтобы 'dict' обрабатывал' 'test_object'' как псевдоним для' some_object'. См. [PEP-455] (http://legacy.python.org/dev/peps/pep-0455/) для предложения, которое добавит новый тип 'dict' с этой функциональностью. – chepner

+0

Возможно ли изменить метод по умолчанию для доступа к объекту в словаре? так что вместо того, чтобы сказать, D ['foo'] проверяет, если t .__ eq __ ('foo') проверяет, является ли t.name .__ eq __ ('foo')? Можно ли переопределить __getitem__? – user3467349

+1

Чепнер ошибается. Вы можете делать то, что хотите. – haael

ответ

1

Вы должны определить eq, который возвращает положительный при сравнении со строкой, а именно:

def __eq__(self, other): 
    if self.name == other: 
     return True 
    ... continue with comparison ... 

Вы должны также определить хэш, который возвращает тот же хэш как сравниваемой строки:

def __hash__(self): 
    return hash(self.name) 

UPDATE: Следующий код делает именно то, что автор хотел:

class test(object): 
    def __init__(self, name, number_array): 
     self.name = name 
     self.number_array = number_array 
     #self.graph= barChart(number_array) 

    def __eq__(self, other): 
     try: 
      return (self.name == other.name) and (self.number_array == other.number_array) 
     except AttributeError: 
      return self.name == other 

    def __hash__(self): 
     return hash(self.name) 

sample_obj = test('test_object', [(0, 1), (2, 3)]) 

dict1 = {sample_obj: "Hurray"} 
print("dict1[sample_obj]", dict1[sample_obj]) 
print("dict1['test_object']", dict1['test_object']) 

dict2 = {'test_object': "Yippie"} 
print("dict2[sample_obj]", dict2[sample_obj]) 
print("dict2['test_object']", dict2['test_object']) 
+0

Для этого потребуется 'str .__ eq__', а не' test .__ eq__', чтобы быть переопределенным. – chepner

+0

Неважно. По умолчанию str .__ eq__ вернет NotImplemented, тогда Python попытается выполнить тест .__ eq__ со строкой в ​​качестве второго аргумента. – haael

1

Чтобы использовать класс в качестве словаря ключ, осуществлять __hash__ и __eq__. Для того, чтобы изменить то, как он появляется при печати словаря, реализовать __repr__:

class Test(object): 

    def __init__(self, name, number_array): 
     self.name = name 
     self.number_array = number_array 
     self.graph = barChart(number_array) 

    def __eq__(self, other): 
     return self.name == other.name and self.number_array == other.number_array 

    def __hash__(self): 
     return hash(self.name)^hash(self.number_array) 

    def __repr__(self): 
     return "test_object" 

При использовании:

>>> t = Test("foo", (1, 2, 3)) 
>>> d = {t: [1, 2, 3]} 
>>> t 
test_object 
>>> d 
{test_object: [1, 2, 3]} 
>>> d[t] 
[1, 2, 3] 

Заметим, что это означает, что оба name и number_array атрибуты должны быть hashable - У меня есть для обеспечения этого использовали строку и кортеж. Кроме того, лучше, если __repr__ более точно представляет фактический объект, например.

def __repr__(self): 
    return "Test({0.name!r}, {0.number_array!r})".format(self) 
+0

Это не относится ко второй части (используя строку «test_object» в качестве ключа для доступа к элементу, сопоставленному объекту), но я не думаю, что такая вещь возможна, по крайней мере, без использования предлагаемого «TransformDict» класс. – chepner

+0

Я получил его для работы с def __repr __ (self): return str (self.name) и def __eq __ (self, other): return self.name == other - Но я не уверен, что это хорошая практика программирования, потому что теперь нет только d ['foo'] работает, но t == 'foo' теперь также вернет true - что кажется довольно опасным. – user3467349

+0

@ user3467349 да, я не уверен, что это хорошая идея. Кроме того, это означает, что все экземпляры 'Test' функционально идентичны, даже если они содержат разные данные. В чем смысл вашего нынешнего подхода? – jonrsharpe

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