2012-11-21 36 views
6

Tôi đang cố gắng tạo hàm băm tùy chỉnh cho chuỗi. Tôi muốn băm chuỗi bởi tần số ký tự của chúng theo trọng lượng. Vì vậy, hiih sẽ mang lại cùng một giá trị băm. Tôi có thể ghi đè __hash__ không?Chuỗi ghi đè Python __hash__

Hoặc đang tạo lớp bao bọc giữ chuỗi và ghi đè __hash____eq__ cách duy nhất?

+0

Tôi muốn sử dụng lớp trình bao bọc. Đó là tốt đẹp và rõ ràng và sẽ không gây nhầm lẫn bằng cách giả vờ là một chuỗi nhưng băm hoàn toàn khác nhau. – millimoose

+0

@millimoose điểm tốt – darksky

+1

Trộn 'str' và' custom_str' trong vùng chứa sử dụng hàm băm làm khóa có thể thú vị :) –

Trả lời

4

Bạn muốn có một loại có nguồn gốc với các ngữ nghĩa bình đẳng khác nhau. Thông thường, cách tiếp cận được thực hiện sẽ là xác định cách thức hoạt động bình đẳng, sau đó xây dựng phương thức băm từ các cấu trúc xuất phát ở đó, vì nó là cần thiết rằng hàm băm đồng ý với sự bình đẳng. Đó có thể là:

import collections 

class FrequencyString(str): 
    @property 
    def normalized(self): 
     try: 
      return self._normalized 
     except AttributeError: 
      self._normalized = normalized = ''.join(sorted(collections.Counter(self).elements())) 
      return normalized 

    def __eq__(self, other): 
     return self.normalized == other.normalized 

    def __hash__(self): 
     return hash(self.normalized) 
+1

Giả sử tôi tạo một hàm miễn phí sẽ trả lại băm. Làm cách nào để chèn khóa đó vào vị trí băm được trả về? Có phải 'dict = {}, dict [5] = giá trị' chèn' giá trị' tại vị trí 5, hay tới khóa '5'? – darksky

+0

đặt các giá trị trong dấu * * ngụ ý thay đổi ngữ nghĩa bình đẳng, đây là cách phù hợp để làm như vậy. Bạn có thể luân phiên cấu trúc trình bao bọc như một phong bì, có chuỗi gốc làm thuộc tính cá thể. – SingleNegationElimination

0

Giả định của bạn là đúng, bạn không thể ghi đè các dấu căn cứ trong Python. Mặc dù có thể, tất nhiên, ghi đè lên những gì str() sẽ làm, nó sẽ không hoạt động đối với chuỗi ký tự.

Nếu bạn đang viết mã cho pre-python 2.2 nhìn vào lớp UserString nếu bạn muốn tạo riêng của bạn: http://docs.python.org/2/library/userdict.html#module-UserString

Nếu không, bạn chỉ có thể kế thừa str hoặc unicode

Trong trường hợp của bạn chỉ đơn giản là ghi đè Phương pháp __hash__ là đủ nếu bạn muốn sử dụng nó làm khóa chính tả. Nhưng nếu bạn đang xem xét so sánh hơn bạn sẽ phải ghi đè __eq__ hoặc __cmp__

+0

Argghghh - không, không & không với 'UserString' - đó là lịch sử cổ đại - chỉ thừa kế từ' str' như 'class mystr (str): ...' –

+0

Nó nói nếu tôi không cần hỗ trợ tính tương thích ngược cho các phiên bản trước 2.2, tôi chỉ có thể phân lớp trực tiếp từ 'str'. Làm thế nào sẽ được thực hiện? Nó sẽ chỉ là: 'class wrapper_class (str):'? Chỉ ghi đè '__hash__' và' __eq__' là đủ? – darksky

+0

@JonClements bạn vừa trả lời phần 1 bình luận của tôi :) Còn những phương pháp ghi đè thì sao? Liệu '__hash__' và' __eq__' có đủ không? – darksky

0

Bạn có thể kế thừa từ str, nhưng vì bạn không thể thay đổi chúng theo phân loại hơi khác. Nhiều khả năng bạn sẽ muốn tạo những cái mới từ các chuỗi hiện có, vì vậy bạn cũng phải ghi đè phương thức __new__. Bạn cũng có thể phải đặt thêm các phương thức đặc biệt để đánh bại các tối ưu hóa mà Python thực hiện.

Dưới đây là ví dụ về phân lớp con được xây dựng trong str, đối tượng mapstr cho phép trình giữ chỗ thay thế dễ dàng trong biểu mẫu.

+0

Bạn có thể giải thích ý của bạn bằng cách "Có thể bạn sẽ muốn tạo những cái mới từ các chuỗi hiện có"? Tôi chỉ muốn tạo một chuỗi mà tôi có thể chuyển vào '__init__', vậy tại sao tôi cần phải phân lớp' __new__'? Điều gì xảy ra nếu tôi không? – darksky

+0

Vậy bạn dự định sử dụng nó như thế nào? – Keith

+0

Làm xâu chuỗi có các ký tự giống nhau trong một phím. Giá trị là danh sách tất cả các chuỗi. Khóa là phiên bản được sắp xếp của chúng. – darksky