2012-01-30 42 views
5

thể trùng lặp:
Python conditional assignment operatorPython tương đương với Perl/Ruby || =

Xin lỗi cho một câu hỏi đơn giản như vậy, nhưng googling ||= không phải là rất hữu ích;)

Có tương đương với Python với câu lệnh ||= có trong Ruby và Perl không?

Ví dụ:

foo = "hey" 
foo ||= "what" # assign foo if it's undefined 
# foo is still "hey" 

bar ||= "yeah" 
# bar is "yeah" 

Ngoài ra thuật ngữ chung cho một cái gì đó như thế này là những gì? Phân công có điều kiện là phỏng đoán đầu tiên của tôi nhưng số Wikipedia page không hoàn toàn là điều tôi nghĩ.

+0

Có vẻ như nó có vẻ trùng lặp. Cảm ơn Adam! –

+2

'$ foo || =" cái gì "' sẽ gán lại '$ foo' nếu nó đã là * false *. Tất nhiên 'undef' là sai, nhưng sau đó là số không và chuỗi rỗng. Để gán lại chỉ một giá trị không xác định sử dụng dấu gạch chéo thay vào đó, như '$ foo // =" what "' – Borodin

+0

Lưu ý rằng '//' (và phần mở rộng của nó, '// =') đã được thêm vào trong perl 5.10. Nếu bạn vẫn bị mắc kẹt trên 5.8.x, bạn sẽ không thể sử dụng '// =' (và bạn nên nghiêm túc xem xét nâng cấp nếu có thể). –

Trả lời

6

tiết hơn Một chút chút, nhưng đơn giản nhất là

foo = "hey" 
foo = foo or "what" 
#foo is still "hey" 

bar = None 
bar = bar or "yeah" 
#bar is "yeah" 

Bạn cũng có thể sử dụng toán tử ternary

bar = None 
bar = bar if bar else "yeah" 

Tuy nhiên, nếu tôi hiểu bạn, ||= gán biến mà không được trước đây được xác định, không có khiếu nại? Tôi không ý kiến.

Để làm điều đó trong phạm vi địa phương, vịt con xấu xí này có thể làm việc

bar = locals()['bar'] if 'bar' in locals() else 'yeah' 

EDIT:

Chỉ cần chứng kiến ​​sự trùng lặp, và nó có rất nhiều giải pháp cũng :) Đối với những người quá lười biếng để nhìn, họ cũng bao gồm một biến thể đẹp hơn trên của tôi cuối cùng một

foo = foo if 'foo' in locals() else 'hey' 

nhưng điều này sẽ không làm việc cho các biến không xác định, chỉ có giá trị falsy sẽ được thay thế và không xác định sẽ nâng cao một NameError. tiếp theo này sẽ, OTOH, CHỈ làm việc cho không xác định và luôn giữ cùng một giá trị falsy từ trước, mà như @Borodin nói là như //= trong Perl

foo = locals().get('foo','hey') 

và, tất nhiên, ai đó đã sử dụng một ngoại lệ :(

.
try: 
    v 
except NameError: 
    v = 'bla bla' 
+0

không, '|| =' sẽ gán lại một biến nếu nó là 'false'. Xem nhận xét của tôi về câu hỏi. Tại sao bạn mong đợi một khiếu nại? – Borodin

+0

Cảm ơn bạn đã trả lời, lúc đầu tôi không nhận thấy sự khác biệt sắc thái. 'bar = None' là cần thiết để nó hoạt động, nếu không nó sẽ ném một' NameError'. Đối với hành vi giống hệt nhau, bạn cần đoạn mã 'locals() ['bar']'. Cảm ơn một lần nữa :) –

+0

@borodin Tôi không phải là người Rubyist, tôi chỉ sử dụng nó cho những thứ ngớ ngẩn như Chef. Tôi chỉ có nghĩa là tôi không biết rằng 'undef' trong Ruby là falsey, vì đó không phải là trường hợp trong Python (không xác định tài liệu tham khảo ném ngoại lệ).Bất kể, nhờ ý kiến ​​của bạn, tôi đã học được điều gì đó :) –

1

Không chắc về tên Điều tốt nhất tôi có thể đưa ra là:

biến
>>> a = 'foo' 
>>> a = 'a' in locals() and a or 'what' 
>>> a 
'foo' 
>>> b = 'b' in locals() and b or 'yeah' 
>>> b 
'yeah' 
2

bạn sẽ hầu như không bao giờ đã không xác định bằng Python, và khi bạn làm điều đó thường có nghĩa là bạn có m ade một sai lầm.Tuy nhiên, thuận tiện, hầu hết các loại giá trị thường được sử dụng làm mặc định (vùng chứa trống, chuỗi có độ dài bằng không, 0 và) là "sai" trong Python, vì vậy đôi khi bạn sẽ thấy những thứ như thế này tận dụng lợi thế khai thác công trình boolean bằng Python:

name = name or "Guido" # if name is empty, set it to "Guido" 
numb = numb or 42  # if numb is zero, set it to 42 

lý do làm việc này là Python dừng đánh giá or nếu đối số đầu tiên là "truthy", được gọi là ngắn mạch, và trong cả hai trường hợp trả về đối số thực tế, chứ không phải là chỉ đơn thuần là True hoặc False, là kết quả của nó. Vì vậy, nếu name là "Jim" thì "Jim" or "Guido" sẽ đánh giá là "Jim""Jim" là một chuỗi có độ dài khác 0 và do đó "trung thực".

Tất nhiên, điều này không hoạt động tốt như vậy khi bạn không biết loại giá trị bạn đang xử lý và/hoặc giá trị "giả" là giá trị hợp lệ. Tuy nhiên, nó hoạt động khá tốt với những thứ như các file cấu hình và raw_input() nơi một giá trị thiếu sẽ trả về một chuỗi rỗng:

name = raw_input("What is your name? ") or "Guido" 

Một thành ngữ phổ biến được sử dụng khi giao dịch với các mục trong một cuốn từ điển. Phương thức get() của lớp từ điển cho phép bạn chỉ định giá trị mặc định sẽ được sử dụng nếu biến không có trong từ điển.

name = values.get("name", "Guido") 

Điều này có thể được sử dụng khi chức năng của bạn được chuyển qua đối số từ khóa sử dụng quy ước **kwargs. Bạn thể cũng sử dụng nó với các biến, như globals()locals() chức năng quay trở lại, tương ứng, tất cả các biến toàn cầu hay địa phương hiện trong phạm vi như một cuốn từ điển:

name = locals().get("name", "Guido") 

Tuy nhiên, như tôi đã nói, bạn sẽ hiếm khi có các biến không xác định thực sự trong Python. Trong các trường hợp như khung Web, bạn sẽ được chuyển đối số chuỗi truy vấn dưới dạng từ điển, ví dụ và có thể sử dụng phương thức .get() của từ điển trên đó. Trong trường hợp hiếm hoi mà tên thực sự không tồn tại (ví dụ, tệp cấu hình của bạn là cú pháp Python và bạn nhập nó như là một mô-đun Python chứ không phải phân tích cú pháp nó, và bạn muốn người dùng có thể bỏ qua một số giá trị ... hoặc một cái gì đó đều lập dị) sau đó bạn có thể sử dụng getattr(), trong đó (như từ điển của .get()) chấp nhận một giá trị mặc định:

import config 
name = getattr(config, "name", "Guido") # rather than just name.config 

hoặc chỉ cần để cho nó ném một NameError và nắm bắt nó.

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