2010-04-09 58 views
7

Vì vậy, tôi có một hình vuông được tạo thành từ một loạt các điểm. Tại mỗi điểm có một giá trị tương ứng.Truy cập giá trị từ điển theo giá trị đối tượng tùy chỉnh bằng Python?

Những gì tôi muốn làm là xây dựng một từ điển như thế này:

class Point: 
    def __init__(self, x, y): 
     self._x = x 
     self._y = y 


square = {}  
for x in range(0, 5): 
     for y in range(0, 5): 
      point = Point(x,y) 
      square[point] = None 

Tuy nhiên, nếu sau này tôi có thể tạo một đối tượng điểm mới và cố gắng truy cập vào các giá trị của từ điển với phím của thời điểm đó nó doesn 't work ..

>> square[Point(2,2)] 
Traceback (most recent call last): 
    File "<pyshell#19>", line 1, in <module> 
    square[Point(2,2)] 
KeyError: <__main__.Point instance at 0x02E6C378> 

Tôi đoán rằng điều này là do python không xem xét hai đối tượng có cùng thuộc tính là cùng một đối tượng? Có cách nào để khắc phục điều này? Cảm ơn

Trả lời

12

Xác định Point.__hash__()Point.__eq__() để chúng có thể được so sánh đúng cách trong phạm vi chữ.

Và trong khi bạn đang ở đó, hãy xem xét xác định Point.__repr__() để bạn có được các đại diện phong nha về các đối tượng Point của mình.

+0

Cảm ơn! Lời khuyên tốt về __repr__ nhưng tôi hơi bối rối về sự khác biệt giữa nó và __str__? – Sam

+1

'__repr __()' được sử dụng bất cứ khi nào bạn cần một đại diện của đối tượng, mà không thực sự muốn giá trị chuỗi, ví dụ: trong REPL. –

+1

'__repr__' cũng phải trả về giá trị python hợp lệ, có thể được chuyển thành arg để' eval' để tạo một đối tượng giống với đối tượng đang được repr'd. Nó sẽ trả về chuỗi sau: ''Điểm (% s,% s)'% (self._x, self._y)' –

5

Có, xác định các phương pháp __eq____hash__ trong lớp Điểm của bạn.

class Point: 
    def __init__(self, x, y): 
     self._x = x 
     self._y = y 

    def __eq__(self, other): 
     return self._x == other._x and self._y == other._y 

    def __hash__(self): 
     #This one's up to you, but it should be unique. Something like x*1000000 + y. 
+0

Cảm ơn sự cố mã, thực sự đã giúp! Ước gì tôi cũng có thể chọn bạn như một câu trả lời. – Sam

+0

Phương thức __hash __() chỉ có thể được thực hiện dưới dạng "trả về (x, y) .__ hash __()". –

2

Bất kỳ lý do để không chỉ cần sử dụng một tuple:

>>> s={} 
>>> s[1,2]=5 
>>> s 
{(1, 2): 5} 
>>> s[1,2] 
5 
+0

Trong ví dụ đó tôi đoán tôi có thể, nhưng trong mã của tôi, lớp Point có thêm một vài thuộc tính để một bộ dữ liệu không đủ. – Sam

+0

Kiểm tra hàm namedtuple trong mô-đun bộ sưu tập. Tôi thấy nó rất hữu ích cho việc thực hiện các đối tượng giống như struct, và nó tạo ra các lớp mà bạn có thể kế thừa từ nếu bạn muốn thêm các phương thức bổ sung. –

2

bước: Thực hiện một lớp tùy chỉnh quan trọng và ghi đè băm và chức năng bình đẳng.

ví dụ:

class CustomDictKey(object): 

def __init__(self, 
      param1, 
      param2): 

      self._param1 = param1 
      self._param2 = param2 

# overriding hash and equality function does the trick 

def __hash__(self): 
    return hash((self._param1, 
      self._param2)) 

def __eq__(self, other): 
    return ((self._param1, 
      self._param2) == (other._param1, 
      other._param2)) 

def __str__(self): 
    return "param 1: {0} param 2: {1} ".format(self._param1, self._param2) 

phương pháp chính

if name == 'main': 

    # create custom key 
    k1 = CustomDictKey(10,5) 

    k2 = CustomDictKey (2, 4) 

    dictionary = {} 

    #insert elements in dictionary with custom key 
    dictionary[k1] = 10 
    dictionary[k2] = 20 

    # access dictionary values with custom keys and print values 
    print "key: ", k1, "val :", dictionary[k1] 
    print "key: ", k2, "val :", dictionary[k2] 

Tham khảo bài viết Using custom class as key in python dictionary để biết chi tiết đầy đủ.

Các vấn đề liên quan