Python, represent non-string object as string?

2019-09-06 21:09发布

I'd like to represent an object as a string so that it can be accessed both as a dictionary key and as an object in itself. i.e.

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.])

but so that {sample_obj: another_object} would look like {'test_object': another_object}

while still making something like this possible:

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

as well as:

>>> sample_dict['test_object']
another_object

标签: python
2条回答
三岁会撩人
2楼-- · 2019-09-06 22:01

To use a class as a dictionary key, implement __hash__ and __eq__. To change how it appears when you print the dictionary, implement __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"

In use:

>>> 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]

Note that this means that both the name and number_array attributes must be hashable - I have used a string and a tuple to ensure this. Also, it is better if __repr__ represents the actual object more closely, e.g.

def __repr__(self):
    return "Test({0.name!r}, {0.number_array!r})".format(self)
查看更多
【Aperson】
3楼-- · 2019-09-06 22:08

You must define eq that returns positive when comparing with the string i.e.:

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

You must also define hash that returns the same hash as the compared string:

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

UPDATE: The following code does exactly what the author wanted:

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'])
查看更多
登录 后发表回答