TL; DR
Chúng ta bắt đầu bằng cách tóm tắt hai hành vi của hai toán tử logic and
và or
. Những thành ngữ này sẽ tạo cơ sở cho cuộc thảo luận của chúng tôi dưới đây.
and
Trả về giá trị Falsy đầu tiên nếu có, nếu không, trả về giá trị cuối cùng trong biểu thức.
or
Trả về giá trị Chân lý đầu tiên nếu có, nếu có, trả về giá trị cuối cùng trong biểu thức.
Hành vi cũng được tóm tắt trong tài liệu , đặc biệt là trong bảng này:
Toán tử duy nhất trả về giá trị boolean bất kể toán hạng của nó là not
toán tử.
Đánh giá "độ tin cậy" và "trung thực"
Tuyên bố
len(args) and max(args) - min(args)
Là một rất pythonic ngắn gọn (và có lẽ ít có thể đọc được) cách khác để nói "nếu args
không được làm rỗng, trả lại kết quả của việc max(args) - min(args)
", nếu không quay trở lại 0
. Nói chung, nó là một biểu diễn ngắn gọn hơn của một if-else
biểu thức. Ví dụ,
exp1 and exp2
Nên (đại khái) dịch thành:
r1 = exp1
if r1:
r1 = exp2
Hoặc, tương đương,
r1 = exp1 if exp1 else exp2
Tương tự,
exp1 or exp2
Tương đương với,
r1 = exp1
if not r1:
r1 = exp2
Ở đâu exp1
và exp2
là các đối tượng python tùy ý hoặc các biểu thức trả về một số đối tượng. Chìa khóa để hiểu cách sử dụng của toán tử and
và lôgic or
ở đây là hiểu rằng chúng không bị giới hạn hoạt động trên hoặc trả về giá trị boolean. Bất kỳ đối tượng nào có giá trị truthiness đều có thể được kiểm tra tại đây. Điều này bao gồm int
, str
, list
, dict
, tuple
, set
, NoneType
, và người sử dụng định nghĩa các đối tượng. Các quy tắc đoản mạch vẫn được áp dụng.
Nhưng tin cậy là gì?
Nó đề cập đến cách các đối tượng được đánh giá khi được sử dụng trong biểu thức điều kiện. @Patrick Haugh tóm tắt về độ tin cậy trong bài đăng này .
Tất cả các giá trị được coi là "đúng" ngoại trừ các giá trị sau, là "sai":
None
False
0
0.0
0j
Decimal(0)
Fraction(0, 1)
[]
- trống rỗng list
{}
- trống rỗng dict
()
- trống rỗng tuple
''
- trống rỗng str
b''
- trống rỗng bytes
set()
- trống rỗng set
- trống rỗng
range
, giống nhưrange(0)
- đối tượng mà
obj.__bool__()
trả lại False
obj.__len__()
trả lại 0
Giá trị "đúng" sẽ thỏa mãn việc kiểm tra được thực hiện bởi if
hoặc các while
câu lệnh. Chúng tôi sử dụng "true" và "falsy" để phân biệt với các
bool
giá trị True
và False
.
Cách and
hoạt động
Chúng tôi xây dựng câu hỏi của OP như một cuộc thảo luận về cách các toán tử này trong những trường hợp này.
Cho một hàm với định nghĩa
def foo(*args):
...
Làm cách nào để trả lại sự khác biệt giữa giá trị tối thiểu và giá trị lớn nhất trong danh sách không hoặc nhiều đối số?
Tìm giá trị tối thiểu và tối đa rất dễ dàng (sử dụng các hàm có sẵn!). Vấn đề duy nhất ở đây là xử lý thích hợp trường hợp góc mà danh sách đối số có thể trống (ví dụ: gọi foo()
). Chúng ta có thể thực hiện cả hai trong một dòng nhờ and
toán tử:
def foo(*args):
return len(args) and max(args) - min(args)
foo(1, 2, 3, 4, 5)
# 4
foo()
# 0
Kể từ khi and
được sử dụng, biểu thức thứ hai cũng phải được đánh giá nếu biểu thức đầu tiên là True
. Lưu ý rằng, nếu biểu thức đầu tiên được đánh giá là đúng, giá trị trả về luôn là kết quả của biểu thức thứ hai . Nếu biểu thức đầu tiên được đánh giá là Falsy, thì kết quả trả về là kết quả của biểu thức đầu tiên.
Trong hàm trên, If foo
nhận một hoặc nhiều đối số len(args)
lớn hơn 0
(một số dương), do đó, kết quả trả về là max(args) - min(args)
. OTOH, nếu không có đối số được truyền, len(args)
là 0
đó là Falsy, và 0
được trả về.
Lưu ý rằng một cách thay thế để viết hàm này sẽ là:
def foo(*args):
if not len(args):
return 0
return max(args) - min(args)
Hay, ngắn gọn hơn,
def foo(*args):
return 0 if not args else max(args) - min(args)
Nếu tất nhiên, không có hàm nào trong số này thực hiện bất kỳ kiểm tra kiểu nào, vì vậy trừ khi bạn hoàn toàn tin tưởng đầu vào được cung cấp, đừng dựa vào tính đơn giản của các cấu trúc này.
Cách or
hoạt động
Tôi giải thích hoạt động của or
một cách tương tự với một ví dụ có sẵn.
Cho một hàm với định nghĩa
def foo(*args):
...
Bạn sẽ hoàn thành như thế nào foo
để trả lại tất cả các số 9000
?
Chúng tôi sử dụng or
để xử lý trường hợp góc ở đây. Chúng tôi định nghĩa foo
là:
def foo(*args):
return [x for x in args if x > 9000] or 'No number over 9000!'
foo(9004, 1, 2, 500)
# [9004]
foo(1, 2, 3, 4)
# 'No number over 9000!'
foo
thực hiện lọc trên danh sách để giữ lại tất cả các số 9000
. Nếu tồn tại bất kỳ số nào như vậy, kết quả của việc hiểu danh sách là một danh sách không trống, là Truthy, vì vậy nó được trả về (viết tắt ở đây). Nếu không tồn tại những con số như vậy, thì kết quả của danh sách comp []
là Falsy. Vì vậy, biểu thức thứ hai bây giờ được đánh giá (một chuỗi không rỗng) và được trả về.
Sử dụng các điều kiện, chúng ta có thể viết lại hàm này thành,
def foo(*args):
r = [x for x in args if x > 9000]
if not r:
return 'No number over 9000!'
return r
Như trước đây, cấu trúc này linh hoạt hơn trong việc xử lý lỗi.
and
(cũng nhưor
) không bị hạn chế làm việc với hoặc trả về các giá trị boolean.