2009-11-05 31 views
6

Về cơ bản, tôi có một danh sách như: [START, 'foo', 'bar', 'spam', eggs', END] và số nhận dạng START/END là cần thiết để sau này tôi có thể so sánh sau này. Ngay bây giờ, tôi đã thiết lập nó như sau:Cách thích hợp để có một mã định danh duy nhất trong Python?

START = object() 
END = object() 

Điều này hoạt động tốt, nhưng nó không gặp vấn đề khi không làm việc. Tôi đã thử làm theo cách sau, nhưng có vẻ như là một phương pháp khủng khiếp để hoàn thành điều này:

class START(object):pass 
class END(object):pass 

Ai có thể chia sẻ phương tiện tốt hơn để làm việc này không? Ngoài ra, ví dụ tôi đã thiết lập ở trên chỉ là sự đơn giản hóa một vấn đề khác.

+0

Tôi nghĩ rằng nó sẽ tốt hơn nếu chỉ gọi nó là một việc đơn giản hóa hơn là "một sự đơn giản hóa" – Casebash

+0

Kể từ những gì bạn đang làm là rất phức tạp (không có giải thích về lý do tại sao), tôi sẽ gọi nó là một "phức tạp" hoặc có lẽ là "quá mức". Các đối tượng Sentinel cơ bản là vô dụng - có rất nhiều cách để tổ chức dữ liệu tốt hơn nhiều. –

+7

S: đó sẽ là một nhận xét hữu ích nếu bạn đã đưa vào một số giải thích về một trong những cách "xa hơn, tốt hơn nhiều". Vì nó là, nó chỉ có vẻ như cua và condescending. –

Trả lời

9

Nếu bạn muốn một đối tượng được đảm bảo là duy nhất cũng có thể được đảm bảo để được khôi phục chính xác cùng một xác nhận nếu được chọn và bỏ lại ngay, chức năng cấp cao nhất, lớp học, lớp thể hiện và nếu bạn quan tâm đến is thay vì == cũng liệt kê (và các mutables khác), tất cả đều ổn. Nghĩa là, bất kỳ:

# work for == as well as is 
class START(object): pass 
def START(): pass 
class Whatever(object): pass 
START = Whatever() 

# if you don't care for "accidental" == and only check with `is` 
START = [] 
START = {} 
START = set() 

Không ai trong số này là khủng khiếp, không có bất kỳ lợi thế đặc biệt (tùy theo nếu bạn quan tâm đến == hoặc chỉ is). Có thể là def thắng bởi dint của tính tổng quát, tính đồng nhất và trọng lượng nhẹ hơn.

+0

Tôi thích tùy chọn # 1 của việc sử dụng lớp như là sentinel, bởi vì nó cung cấp các ngoại lệ thông tin nhất - bạn nhận được AttributeError's xác định giá trị không thành công. Mặc dù nó hơi kỳ lạ ở chỗ nó sẽ cho phép bạn tạo ra các đối tượng, nhưng không có cách nào đơn giản để ngăn chặn điều đó, và nó thực sự không phải là một vấn đề lớn. – acjay

0

Tôi nghĩ rằng có lẽ đây sẽ dễ dàng hơn để trả lời nếu bạn đã rõ ràng hơn về những gì bạn cần điều này cho, nhưng khuynh hướng của tôi nếu phải đối mặt với một vấn đề như thế này sẽ là một cái gì đó như:

>>> START = os.urandom(16).encode('hex') 
>>> END = os.urandom(16).encode('hex') 

Ưu điểm của việc này cách tiếp cận, như tôi nhìn thấy nó

  • dấu của bạn là chuỗi (có thể dưa hoặc nếu không dễ serialize, ví dụ như để JSON hoặc một DB, mà không cần bất kỳ nỗ lực đặc biệt)
  • rất khó có khả năng va chạm hoặc là vô tình hay cố
  • Sẽ tuần tự hóa và sắp xếp lại thành các giá trị giống hệt nhau, ngay cả trong quá trình khởi động lại, mà (tôi nghĩ) sẽ không phải là trường hợp cho object() hoặc một lớp trống.

Nhược điểm (?)

  • Mỗi lần họ mới được lựa chọn họ sẽ hoàn toàn khác nhau. (Điều này là tốt hay xấu phụ thuộc vào chi tiết bạn đã không cung cấp, tôi sẽ nghĩ).
+0

Xin lỗi, nhưng điều này không có tác dụng nếu tôi chọn kết quả và mở nó ra trong một quy trình riêng biệt vì giờ đây mỗi bước khác nhau. –

+0

Tôi * thực sự * không thích giải pháp này (tôi biết cơ hội va chạm là nhỏ, nhưng nếu nó xảy ra bạn thực sự nhồi!), Nhưng bạn đã liệt kê những hạn chế, vì vậy tôi chống lại yêu cầu của tôi để downvote – Casebash

+1

@Casebash Có 1/2^64 có vẻ là một xác suất không hợp lý cao đối với bạn không, hoặc bạn có lý do để tin/dev/* ngẫu nhiên bị hỏng không? –

1

Nếu danh sách của bạn không có chuỗi, tôi chỉ sử dụng "bắt đầu", "kết thúc" khi Python so sánh O (1) do thực tập.

Nếu bạn cần dây, nhưng không phải các bộ, phương pháp kẻ bần tiện hoàn chỉnh là:

[("START",), 'foo', 'bar', 'spam', eggs', ("END",)] 

PS: Tôi đã chắc chắn danh sách của bạn được số trước, không dây, nhưng tôi có thể không nhìn thấy bất kỳ sửa đổi để Tôi phải tưởng tượng nó

1

Thực ra, tôi thích giải pháp của bạn.

Một thời gian sau tôi đã hack vào một mô-đun Python, và tôi muốn có một giá trị phép thuật đặc biệt mà không thể xuất hiện ở bất kỳ nơi nào khác. Tôi đã dành một chút thời gian suy nghĩ về nó và tốt nhất tôi nghĩ ra là một mẹo mà bạn đã sử dụng: khai báo một lớp, và sử dụng đối tượng lớp làm giá trị phép thuật đặc biệt.

Khi bạn đang kiểm tra cho các trọng điểm, bạn nên sử dụng tất nhiên các nhà điều hành is, cho nhận dạng đối tượng:

for x in my_list: 
    if x is START: 
     # handle start of list 
    elif x is END: 
     # handle end of list 
    else: 
     # handle item from list 
+0

Nếu bạn khai báo lớp của riêng bạn == sẽ chỉ kiểm tra danh tính theo mặc định – Casebash

+3

Đúng, nhưng tôi không khuyên bạn nên sử dụng nó. Nếu bạn viết '==' khi bạn thực sự có nghĩa là 'is', bạn không thể hiện rõ ý định của mình.Và tôi không chắc chắn nó có khả năng như thế nào, nhưng có thể ai đó có thể viết một lớp có phương thức '__cmp __()' trả về 0 khi nó so sánh với lớp sentinel của bạn. (Tôi chỉ viết một cái như là một bằng chứng về khái niệm ...) Nếu bạn sử dụng 'is' bạn biết chính xác nó sẽ làm gì. – steveha

2

Bạn có thể định nghĩa một lớp Symbol để xử lý START và END.

class Symbol: 
    def __init__(self, value): 
     self.value = value 

    def __eq__(self, other): 
     return isinstance(other, Symbol) and other.value == self.value 

    def __repr__(self): 
     return "<sym: %r>" % self.value 

    def __str__(self): 
     return str(self.value) 

START = Symbol("START") 
END = Symbol("END") 

# test pickle 
import pickle 
assert START == pickle.loads(pickle.dumps(START)) 
assert END == pickle.loads(pickle.dumps(END)) 
+0

Tôi đã thực sự làm theo cách này trong một thời gian. –

+0

Vậy tại sao bạn muốn chuyển sang một số cách tiếp cận khác? Trên thực tế, một số ngôn ngữ khác có hỗ trợ tích hợp cho các ký hiệu. Trong Ruby, bạn có thể viết ': start' và': end' để bắt đầu và dừng các ký hiệu. –

+0

Trong Python, chuỗi được dự định sẽ được sử dụng làm biểu tượng. Ngoại trừ đôi khi chúng tôi cũng muốn sử dụng các chuỗi, vì vậy chúng tôi cần những cách tiếp cận khác này – Casebash

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