Hướng dẫn python or operator with none - python hoặc toán tử không có

Làm thế nào để Python hoặc toán tử hoạt động với không có loại?

Show

Không ai được hiểu là sai. is interpreted as false.

print(a.next) # None
print(a.next or False) # False
print(a.next or True) # True

Từ tài liệu:

Trong bối cảnh của các hoạt động Boolean và cả khi các biểu thức được sử dụng bởi các câu lệnh luồng điều khiển, các giá trị sau được hiểu là sai: sai, không, số 0 của tất cả các loại, và các chuỗi trống (bao gồm cả chuỗi, bộ dữ liệu, danh sách, từ điển , bộ và đông lạnh).None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets).

Biểu thức x hoặc y trước tiên đánh giá x; Nếu x là đúng, giá trị của nó được trả về; Mặt khác, y được đánh giá và giá trị kết quả được trả về.

Tuy nhiên, nếu tôi sắp xếp lại các biểu thức trong hoặc biểu thức, nó sẽ gây ra lỗi.

if a.next is None or a.next.next is None

hoặc đây là logic hoặc hoặc phân tách. here is logical OR or disjunction.

Tôi nghi ngờ bạn đã thay đổi biểu thức với toán tử

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
8 (bao gồm bitwise hoặc).

if a.next is None | a.next.next is None

Nếu bạn thay đổi biểu thức với | toán tử, sau đó bạn gặp lỗi:| operator, then you get the error:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'

Bạn có thể kiểm tra cuộc thảo luận này để đi sâu vào các chi tiết cụ thể của Python: Nhà khai thác Boolean so với các toán tử bitwise

Suy nghĩ đầu tiên của tôi là Python đánh giá biểu thức đầu tiên (a.next là không có), đánh giá nó là đúng, nhìn thấy người vận hành OR và biết rằng vì biểu thức đầu tiên là đúng, phần còn lại của câu lệnh OR có thể bị bỏ qua.

Đúng rồi. Xem các hoạt động của Boolean trong Python.

Ngoài ra, điều này có tên không, và nếu vậy, nó có được sử dụng trong các ngôn ngữ lập trình khác không?

Điều này được gọi là đánh giá ngắn mạch.

Python hoặc là một toán tử ngắn mạch, vì vậy nó chỉ đánh giá đối số thứ hai nếu câu thứ nhất là sai.or is a short-circuit operator, so it only evaluates the second argument if the first one is false.

Tác giả: Mark E. Haase, Steve Dower Trạng thái: ReferredType: Tiêu chuẩn theo dõi: 18-SEP-2015Python-Version: 3.8:Mark E. Haase , Steve Dower Status:DeferredType:Standards TrackCreated:18-Sep-2015Python-Version:3.8
Mục lục
  • trừu tượng
  • Cú pháp và ngữ nghĩa
    • Đặc biệt của
      augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                  '<<=' | '>>=' | '**=' | '//=' | '??=')
      
      power: coalesce ['**' factor]
      coalesce: atom_expr ['??' factor]
      atom_expr: ['await'] atom trailer*
      trailer: ('(' [arglist] ')' |
                '[' subscriptlist ']' |
                '?[' subscriptlist ']' |
                '.' NAME |
                '?.' NAME)
      
      9
    • Ngữ pháp thay đổi
      • Quy tắc hợp tác
      • Các toán tử có thể là dot và có thể subscript
    • Đọc biểu thức
  • Ví dụ
    • Thư viện tiêu chuẩn
    • Jsonify
    • Vồ lấy
  • Từ chối ý tưởng
    • Giao thức không có giá trị
    • Các nhà khai thác nhận biết Boolean
    • Các nhà khai thác nhận biết ngoại lệ
    • ________ 49-nhận biết chức năng gọi
    • a, b = None, None
      def c(): return None
      def ex(): raise Exception()
      
      (a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
      (a * b ?? c // d) == a * (b ?? c) // d
      (a ?? True and b ?? False) == (a ?? True) and (b ?? False)
      (c() ?? c() ?? True) == True
      (True ?? ex()) == True
      (c ?? ex)() == c()
      
      1 Nhà điều hành Postfix Unary
    • Tích hợp
      a, b = None, None
      def c(): return None
      def ex(): raise Exception()
      
      (a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
      (a * b ?? c // d) == a * (b ?? c) // d
      (a ?? True and b ?? False) == (a ?? True) and (b ?? False)
      (c() ?? c() ?? True) == True
      (True ?? ex()) == True
      (c ?? ex)() == c()
      
      2
    • Chỉ cần sử dụng một biểu thức có điều kiện
  • Người giới thiệu
  • Bản quyền

trừu tượng

Cú pháp và ngữ nghĩa

  • Đặc biệt của
    augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                '<<=' | '>>=' | '**=' | '//=' | '??=')
    
    power: coalesce ['**' factor]
    coalesce: atom_expr ['??' factor]
    atom_expr: ['await'] atom trailer*
    trailer: ('(' [arglist] ')' |
              '[' subscriptlist ']' |
              '?[' subscriptlist ']' |
              '.' NAME |
              '?.' NAME)
    
    9
  • Ngữ pháp thay đổi
  • Quy tắc hợp tác

Các toán tử có thể là dot và có thể subscript

  • Các nhà điều hành nhị phân của ____ ____49 kết hợp với nhau,
    a = None
    b = ''
    c = 0
    
    a ??= 'value'
    b ??= undefined_name
    c ??= shutil.rmtree('/')    # don't try this at home, kids
    
    assert a == 'value'
    assert b == ''
    assert c == 0 and any(os.scandir('/'))
    
    5 trả về phía bên trái nếu nó đánh giá thành một giá trị không phải là
    augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                '<<=' | '>>=' | '**=' | '//=' | '??=')
    
    power: coalesce ['**' factor]
    coalesce: atom_expr ['??' factor]
    atom_expr: ['await'] atom trailer*
    trailer: ('(' [arglist] ')' |
              '[' subscriptlist ']' |
              '?[' subscriptlist ']' |
              '.' NAME |
              '?.' NAME)
    
    9, hoặc nếu không nó đánh giá và trả lại phía bên tay phải. Một nhà điều hành phân công tăng cường
    a = None
    b = ''
    c = 0
    
    a ??= 'value'
    b ??= undefined_name
    c ??= shutil.rmtree('/')    # don't try this at home, kids
    
    assert a == 'value'
    assert b == ''
    assert c == 0 and any(os.scandir('/'))
    
    7 được bao gồm.
  • Trình điều khiển Access Access Access Access Access Access
    a = None
    b = ''
    c = 0
    
    a ??= 'value'
    b ??= undefined_name
    c ??= shutil.rmtree('/')    # don't try this at home, kids
    
    assert a == 'value'
    assert b == ''
    assert c == 0 and any(os.scandir('/'))
    
    9 (có thể có thể chấm điểm) đánh giá biểu thức hoàn chỉnh nếu phía bên trái đánh giá theo giá trị không phải là
    augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                '<<=' | '>>=' | '**=' | '//=' | '??=')
    
    power: coalesce ['**' factor]
    coalesce: atom_expr ['??' factor]
    atom_expr: ['await'] atom trailer*
    trailer: ('(' [arglist] ')' |
              '[' subscriptlist ']' |
              '?[' subscriptlist ']' |
              '.' NAME |
              '?.' NAME)
    
    9
  • Các nhà điều hành lập chỉ mục nhận biết của ____ ____ 49
    _v = a
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    _v = _v[e]
    await _v
    
    2 (có thể là người đăng ký) đánh giá biểu thức hoàn chỉnh nếu trang web bên trái đánh giá thành một giá trị không phải là
    augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
                '<<=' | '>>=' | '**=' | '//=' | '??=')
    
    power: coalesce ['**' factor]
    coalesce: atom_expr ['??' factor]
    atom_expr: ['await'] atom trailer*
    trailer: ('(' [arglist] ')' |
              '[' subscriptlist ']' |
              '?[' subscriptlist ']' |
              '.' NAME |
              '?.' NAME)
    
    9

Xem phần Thay đổi ngữ pháp để biết chi tiết cụ thể và ví dụ về các thay đổi ngữ pháp cần thiết.

Xem phần ví dụ để biết các ví dụ thực tế hơn về mã có thể được cập nhật để sử dụng các toán tử mới.

Cú pháp và ngữ nghĩa

Đặc biệt của augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' | '??=') power: coalesce ['**' factor] coalesce: atom_expr ['??' factor] atom_expr: ['await'] atom trailer* trailer: ('(' [arglist] ')' | '[' subscriptlist ']' | '?[' subscriptlist ']' | '.' NAME | '?.' NAME) 9

Đối tượng

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 biểu thị sự thiếu giá trị. Đối với mục đích của các toán tử này, việc thiếu giá trị chỉ ra rằng phần còn lại của biểu thức cũng thiếu giá trị và không nên được đánh giá.

Một đề xuất bị từ chối là đối xử với bất kỳ giá trị nào đánh giá là sai lầm trong bối cảnh boolean vì không có giá trị. Tuy nhiên, mục đích của các nhà khai thác này là tuyên truyền sự thiếu hụt giá trị của trạng thái, chứ không phải là trạng thái sai.

Một số người cho rằng điều này làm cho

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 đặc biệt. Chúng tôi cho rằng
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 đã rất đặc biệt và việc sử dụng nó như cả thử nghiệm và kết quả của các toán tử này không thay đổi ngữ nghĩa hiện có theo bất kỳ cách nào.

Xem phần Ý tưởng bị từ chối để thảo luận về các phương pháp thay thế.

Ngữ pháp thay đổi

Các quy tắc sau đây của ngữ pháp Python được cập nhật để đọc:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)

Quy tắc hợp tác

Quy tắc

_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v
8 cung cấp toán tử nhị phân
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5. Không giống như hầu hết các toán tử nhị phân, phía bên phải không được đánh giá cho đến khi phía bên trái được xác định là
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9.

Toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5 liên kết chặt chẽ hơn các toán tử nhị phân khác vì hầu hết các triển khai hiện tại của các giá trị này không truyền các giá trị
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 (chúng thường sẽ tăng
_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
3). Các biểu thức được biết là có khả năng dẫn đến
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 có thể được thay thế cho một giá trị mặc định mà không cần dấu ngoặc đơn bổ sung.

Một số ví dụ về cách đặt dấu ngoặc đơn được đặt khi đánh giá ưu tiên toán tử với sự có mặt của toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5:

a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()

Đặc biệt đối với các trường hợp như

_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
6, dấu ngoặc đơn biểu hiện phụ bất kỳ cách nào khác sẽ dẫn đến
_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
3, vì
_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
8 không thể được gọi bằng
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 (và thực tế là toán tử
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5 được sử dụng ở tất cả các ngụ ý rằng
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
1 hoặc
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
2 có thể là. Tuy nhiên, như thường lệ, trong khi dấu ngoặc đơn không bắt buộc, chúng nên được thêm vào nếu nó giúp cải thiện khả năng đọc.

Một nhiệm vụ tăng cường cho toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5 cũng được thêm vào. Nhiệm vụ kết hợp tăng cường chỉ làm cho tên này nếu giá trị hiện tại của nó là
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9. Nếu tên đích đã có giá trị, phía bên phải không được đánh giá. Ví dụ:

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))

Các toán tử có thể là dot và có thể subscript

Các toán tử có thể chấm và có thể được thêm vào làm đoạn giới thiệu cho các nguyên tử, do đó chúng có thể được sử dụng ở tất cả các vị trí giống như các toán tử thông thường, bao gồm cả một phần của mục tiêu gán (chi tiết bên dưới). Vì các quy tắc đánh giá hiện tại không được nhúng trực tiếp vào ngữ pháp, chúng tôi chỉ định các thay đổi cần thiết dưới đây.

Giả sử rằng

# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
6 luôn được đánh giá thành công. Mỗi
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
7 sau đó được đánh giá từ trái sang phải, áp dụng tham số riêng (đối số, chỉ số hoặc tên thuộc tính của nó) để tạo giá trị cho
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
7 tiếp theo. Cuối cùng, nếu có,
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
9 được áp dụng.

Ví dụ,

if a.next is None or a.next.next is None
00 hiện đang được phân tích cú pháp là
if a.next is None or a.next.next is None
01 và được đánh giá:

_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v

Khi có một toán tử nhận biết ____ 49, đánh giá từ trái sang phải có thể được ngắn mạch. Ví dụ,

if a.next is None or a.next.next is None
03 được đánh giá:

_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v

Ghi chú

# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
9 gần như chắc chắn sẽ thất bại trong bối cảnh này, như trong trường hợp mã cố gắng
if a.next is None or a.next.next is None
05. Chúng tôi không đề xuất thêm từ khóa ________ 49 nhận biết
# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
9 ở đây và chỉ bao gồm nó trong ví dụ này để hoàn thành thông số kỹ thuật, vì quy tắc ngữ pháp ____108 bao gồm từ khóa. Nếu nó ở trong quy tắc riêng của nó, chúng tôi sẽ không bao giờ đề cập đến nó.

Các biểu thức được xử lý theo quy tắc

# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e
6 (không được hiển thị ở trên), sẽ hoàn toàn chấm dứt hành vi ngắn mạch của chuyển đổi trên. Ví dụ,
if a.next is None or a.next.next is None
10 được đánh giá là:

# a?.b
_v = a
if _v is not None:
    _v = _v.b

# ... ?? c
if _v is None:
    _v = c

# (...).d?.e
_v = _v.d
if _v is not None:
    _v = _v.e

Khi được sử dụng như một mục tiêu gán, các hoạt động nhận biết ____ 49 chỉ có thể được sử dụng trong bối cảnh tải trọng. Đó là,

if a.next is None or a.next.next is None
12 và
if a.next is None or a.next.next is None
13 sẽ tăng
if a.next is None or a.next.next is None
14. Sử dụng trước đó trong biểu thức (
if a.next is None or a.next.next is None
15) được cho phép, mặc dù không có khả năng hữu ích trừ khi kết hợp với hoạt động hợp nhất:

Đọc biểu thức

Đối với các nhà khai thác có thể chấm và có thể là subscript, ý định là các biểu thức bao gồm các toán tử này nên được đọc và giải thích là đối với các phiên bản thông thường của các toán tử này. Trong các trường hợp bình thường, các kết quả cuối cùng sẽ giống hệt nhau giữa một biểu thức như

if a.next is None or a.next.next is None
16 và
if a.next is None or a.next.next is None
17, và giống như chúng ta hiện không đọc Tăng thuộc tính, không cần phải đọc một cách?

Đối với các biểu thức kết hợp bằng cách sử dụng toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5, các biểu thức nên được đọc dưới dạng hoặc hoặc nếu không có ai hoặc kết hợp với nhau. Ví dụ: biểu thức
if a.next is None or a.next.next is None
19 sẽ được đọc, hãy gọi một dấu chấm get_value hoặc 100 nếu không có ai, hoặc gọi một dấu chấm get_value kết hợp với 100.

Ghi chú

Đọc mã trong văn bản nói luôn luôn mất, và vì vậy chúng tôi không cố gắng xác định một cách nói rõ ràng để nói các nhà khai thác này. Những đề xuất này nhằm thêm bối cảnh vào ý nghĩa của việc thêm cú pháp mới.

Ví dụ

Phần này trình bày một số ví dụ về các mẫu

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 phổ biến và cho thấy những gì chuyển đổi để sử dụng các toán tử nhận biết ____ 49 có thể trông như thế nào.

Thư viện tiêu chuẩn

Sử dụng tập lệnh

if a.next is None or a.next.next is None
22 [5] _ Một phân tích về thư viện tiêu chuẩn Python 3.7 được phát hiện lên tới 678 đoạn mã có thể được thay thế bằng việc sử dụng một trong các toán tử nhận biết ____ 49:

if a.next is None or a.next.next is None
0

Một số trong số này được hiển thị dưới đây là ví dụ trước và sau khi chuyển đổi để sử dụng các toán tử mới.

Từ

if a.next is None or a.next.next is None
24:

if a.next is None or a.next.next is None
1

Sau khi cập nhật để sử dụng câu lệnh gán tăng cường

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
7:

if a.next is None or a.next.next is None
2

Từ

if a.next is None or a.next.next is None
26:

if a.next is None or a.next.next is None
3

Sau khi cập nhật để sử dụng toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5:

if a.next is None or a.next.next is None
4

Từ

if a.next is None or a.next.next is None
28 (và quan trọng lưu ý rằng không có cách nào để thay thế
if a.next is None or a.next.next is None
29 cho
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5 trong tình huống này):

if a.next is None or a.next.next is None
5

Sau khi cập nhật:

if a.next is None or a.next.next is None
6

Từ

if a.next is None or a.next.next is None
31:

if a.next is None or a.next.next is None
7

Sau khi cập nhật để sử dụng toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9:

if a.next is None or a.next.next is None
8

Từ

if a.next is None or a.next.next is None
33:

if a.next is None or a.next.next is None
9

Sau khi cập nhật để sử dụng toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9:

if a.next is None | a.next.next is None
0

Từ

if a.next is None or a.next.next is None
33:

if a.next is None | a.next.next is None
1

Sau khi cập nhật:

if a.next is None | a.next.next is None
2

Từ

if a.next is None or a.next.next is None
31:

if a.next is None | a.next.next is None
3

Sau khi cập nhật để sử dụng toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9:

if a.next is None | a.next.next is None
4

Từ

if a.next is None or a.next.next is None
33:

if a.next is None | a.next.next is None
5

Từ

if a.next is None or a.next.next is None
35:

if a.next is None | a.next.next is None
6

Từ

if a.next is None or a.next.next is None
36:

if a.next is None | a.next.next is None
7

Từ

if a.next is None or a.next.next is None
38:

if a.next is None | a.next.next is None
8

Sau khi cập nhật một phần:

if a.next is None | a.next.next is None
9

Sau khi cập nhật rộng rãi (được cho là quá mức, mặc dù điều đó cho các hướng dẫn kiểu để xác định):

Từ

if a.next is None or a.next.next is None
39:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
0

Sau khi cập nhật để sử dụng các toán tử

_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v
2 và
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5:

Jsonify

Ví dụ này là từ một trình thu thập thông tin web Python sử dụng khung Flask làm mặt trước của nó. Chức năng này lấy thông tin về một trang web từ cơ sở dữ liệu SQL và định dạng nó là JSON để gửi cho máy khách HTTP:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
1

Cả

if a.next is None or a.next.next is None
42 và
if a.next is None or a.next.next is None
43 đều được phép là
a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
3 trong cơ sở dữ liệu và chúng cũng được phép là
a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
3 trong phản hồi JSON. JSON không có cách gốc để biểu diễn
if a.next is None or a.next.next is None
46, do đó, hợp đồng máy chủ nói rằng bất kỳ ngày nào không phải là ngày 53 được biểu diễn dưới dạng chuỗi ISO-8601.

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
2

Không biết các ngữ nghĩa chính xác của các thuộc tính if a.next is None or a.next.next is None 42 và if a.next is None or a.next.next is None 43, không thể biết liệu thuộc tính có thể được truy cập một cách an toàn hay thực hiện nhiều lần.

Một cách để khắc phục mã này là thay thế từng biểu thức có điều kiện bằng một gán giá trị rõ ràng và khối ________ 150/________ 151 đầy đủ:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
3

Điều này thêm mười dòng mã và bốn đường dẫn mã mới vào hàm, làm tăng đáng kể độ phức tạp rõ ràng. Viết lại bằng cách sử dụng toán tử thuộc tính ____ 49-nhận biết kết quả trong mã ngắn hơn với ý định rõ ràng hơn:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
4

Vồ lấy

Ví dụ tiếp theo là từ một thư viện cào python có tên là Grab:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
5

Ví dụ này chứa một số ví dụ tốt về việc cần cung cấp các giá trị mặc định. Viết lại để sử dụng các biểu thức có điều kiện làm giảm các dòng mã tổng thể, nhưng không nhất thiết phải cải thiện khả năng đọc:

Từ chối ý tưởng

Ba ý tưởng đầu tiên trong phần này là các lựa chọn thay thế được đề xuất để coi

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 là đặc biệt. Để biết thêm về lý do tại sao những điều này bị từ chối, hãy xem điều trị của họ trong PEP 531 và PEP 532 và các cuộc thảo luận liên quan.

Giao thức không có giá trị

Các toán tử có thể được khái quát hóa thành các loại do người dùng xác định bằng cách xác định giao thức để cho biết khi nào một giá trị đại diện cho giá trị không có giá trị. Một giao thức như vậy có thể là một phương pháp

if a.next is None or a.next.next is None
58 trả về
if a.next is None or a.next.next is None
59 nếu giá trị nên được coi là có giá trị và
if a.next is None or a.next.next is None
60 nếu giá trị được coi là không có giá trị.

Với sự khái quát hóa này,

if a.next is None or a.next.next is None
61 sẽ thực hiện một phương pháp Dunder tương đương với điều này:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
6

if a.next is None or a.next.next is None
62 sẽ thực hiện một phương pháp Dunder tương đương với điều này:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
7

Trong phần Đặc điểm kỹ thuật, tất cả các cách sử dụng của

if a.next is None or a.next.next is None
63 sẽ được thay thế bằng
if a.next is None or a.next.next is None
64.

Việc khái quát hóa này sẽ cho phép các đối tượng không có giá trị cụ thể của miền được kết hợp giống như

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9. Ví dụ: gói
if a.next is None or a.next.next is None
66 có một loại gọi là
if a.next is None or a.next.next is None
67 đại diện cho ASN.1
a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
3:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
8

Tương tự, các giá trị như

if a.next is None or a.next.next is None
69 và
if a.next is None or a.next.next is None
70 có thể được coi là không đại diện cho giá trị.

Tuy nhiên, bản chất không có giá trị của người Viking của các giá trị này là dành riêng cho miền, điều đó có nghĩa là chúng nên được coi là một giá trị bằng ngôn ngữ. Ví dụ:

if a.next is None or a.next.next is None
71 được xác định rõ (đó là
if a.next is None or a.next.next is None
72), và do đó, ngắn mạch
if a.next is None or a.next.next is None
73 để trả về
if a.next is None or a.next.next is None
69 sẽ không chính xác.

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 đã được ngôn ngữ định nghĩa là giá trị đại diện cho không có giá trị, và thông số kỹ thuật hiện tại sẽ không loại trừ việc chuyển sang giao thức trong tương lai (mặc dù các thay đổi đối với các đối tượng tích hợp sẽ không tương thích), ý tưởng này là Bị từ chối bây giờ.

Các nhà khai thác nhận biết Boolean

Đề xuất này về cơ bản giống như thêm một giao thức không có giá trị, và do đó, các cuộc thảo luận ở trên cũng được áp dụng.

Hành vi tương tự với toán tử

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5 có thể đạt được bằng biểu thức
if a.next is None or a.next.next is None
29, tuy nhiên
if a.next is None or a.next.next is None
29 kiểm tra xem toán hạng bên trái của nó có sai-y không và không cụ thể là
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9. Cách tiếp cận này là hấp dẫn, vì nó đòi hỏi ít thay đổi hơn đối với ngôn ngữ, nhưng cuối cùng không giải quyết được vấn đề cơ bản một cách chính xác.

Giả sử séc là sự thật thay vì

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, không còn cần nhà điều hành
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
5. Tuy nhiên, áp dụng séc này cho các nhà khai thác
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9 và
_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v
2 ngăn chặn các hoạt động hoàn toàn hợp lệ áp dụng

Hãy xem xét ví dụ sau, trong đó

if a.next is None or a.next.next is None
84 có thể trả về danh sách chứa các thông báo nhật ký hiện tại (có khả năng trống) hoặc
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 nếu đăng nhập không được bật:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    if a.next is None | a.next.next is None:
AttributeError: 'NoneType' object has no attribute 'next'
9

Nếu

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9 đang kiểm tra các giá trị thực thay vì cụ thể
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 và nhật ký chưa được khởi tạo với bất kỳ mục nào, sẽ không có mục nào được thêm vào. Điều này vi phạm mục đích rõ ràng của mã, đó là nối lại một mục. Phương pháp
if a.next is None or a.next.next is None
88 có sẵn trong một danh sách trống, vì tất cả các phương thức danh sách khác và không có lý do gì để cho rằng các thành viên này không nên được sử dụng vì danh sách hiện đang trống.

Hơn nữa, không có kết quả hợp lý để sử dụng thay cho biểu thức. Một

if a.next is None or a.next.next is None
89 bình thường trả về
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, nhưng theo ý tưởng này
if a.next is None or a.next.next is None
91 có thể dẫn đến
if a.next is None or a.next.next is None
92 hoặc
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, tùy thuộc vào giá trị của
if a.next is None or a.next.next is None
94. Như với các ví dụ trong phần trước, điều này không có ý nghĩa gì.

Vì kiểm tra sự thật hơn là

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 dẫn đến các biểu thức rõ ràng hợp lệ không còn thực thi như dự định, ý tưởng này bị từ chối.

Các nhà khai thác nhận biết ngoại lệ

Có thể cho rằng, lý do để ngắn mạch một biểu thức khi gặp phải

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 là để tránh
if a.next is None or a.next.next is None
97 hoặc
_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
3 sẽ được nêu ra trong những trường hợp bình thường. Thay vào đó là một phương án để thử nghiệm cho
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, các toán tử
a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9 và
_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v
2 thay vào đó có thể xử lý
if a.next is None or a.next.next is None
97 và
_v = a
if _v is not None:
    _v = _v.b
    _v = _v(c)
    _v = _v.d
    if _v is not None:
        _v = _v[e]
await _v
3 được nâng lên bởi hoạt động và bỏ qua phần còn lại của biểu thức.

Điều này tạo ra sự chuyển đổi cho

if a.next is None | a.next.next is None
04 tương tự như thế này:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
0

Một câu hỏi mở là giá trị nào sẽ được trả về làm biểu thức khi một ngoại lệ được xử lý. Ví dụ trên chỉ đơn giản là để lại kết quả một phần, nhưng điều này không hữu ích cho việc thay thế bằng giá trị mặc định. Một giải pháp thay thế sẽ là buộc kết quả đối với

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, sau đó đặt ra câu hỏi về lý do tại sao
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9 là đủ đặc biệt để trở thành kết quả nhưng không đủ đặc biệt để trở thành bài kiểm tra.

Thứ hai, cách tiếp cận này che dấu các lỗi trong mã được thực thi ngầm như một phần của biểu thức. Đối với

a = None
b = ''
c = 0

a ??= 'value'
b ??= undefined_name
c ??= shutil.rmtree('/')    # don't try this at home, kids

assert a == 'value'
assert b == ''
assert c == 0 and any(os.scandir('/'))
9, bất kỳ
if a.next is None or a.next.next is None
97 nào trong một tài sản hoặc triển khai
if a.next is None | a.next.next is None
09 sẽ được ẩn và tương tự cho việc triển khai
_v = a
_v = _v.b
_v = _v(c)
_v = _v.d
_v = _v[e]
await _v
2 và
if a.next is None | a.next.next is None
11.

Tương tự, các lỗi gõ đơn giản như

if a.next is None | a.next.next is None
12 có thể không được chú ý.

Các quy ước hiện tại để xử lý các loại lỗi này dưới dạng

if a.next is None | a.next.next is None
13 tích hợp và mẫu phương thức
if a.next is None | a.next.next is None
14 được thiết lập bởi
if a.next is None | a.next.next is None
15 cho thấy rằng có thể sử dụng rõ ràng hành vi này.

Vì cách tiếp cận này sẽ ẩn lỗi trong mã, nó bị từ chối.

________ 49-nhận biết chức năng gọi

Cú pháp nhận biết ____ 49 áp dụng cho quyền truy cập thuộc tính và chỉ mục, do đó, có vẻ tự nhiên để hỏi liệu nó cũng nên áp dụng cho cú pháp gọi chức năng. Nó có thể được viết là

if a.next is None | a.next.next is None
18, trong đó
if a.next is None | a.next.next is None
19 chỉ được gọi nếu không phải là không.

Điều này đã được hoãn lại trên cơ sở các nhà khai thác được đề xuất nhằm hỗ trợ các cấu trúc dữ liệu phân cấp đông dân cư, không phải đối với các hệ thống phân cấp lớp tùy ý. Điều này được phản ánh trong thực tế rằng không có ngôn ngữ chính nào khác cung cấp cú pháp này đã thấy đáng để hỗ trợ một cú pháp tương tự cho các yêu cầu chức năng tùy chọn.

Một cách giải quyết tương tự như được sử dụng bởi C# sẽ là viết

if a.next is None | a.next.next is None
20. Nếu có thể gọi là
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, biểu thức sẽ không được đánh giá. (Tương đương C# sử dụng
if a.next is None | a.next.next is None
22 trên loại có thể gọi của nó.)

a, b = None, None def c(): return None def ex(): raise Exception() (a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3)) (a * b ?? c // d) == a * (b ?? c) // d (a ?? True and b ?? False) == (a ?? True) and (b ?? False) (c() ?? c() ?? True) == True (True ?? ex()) == True (c ?? ex)() == c() 1 Nhà điều hành Postfix Unary

Để khái quát hóa hành vi nhận biết ____ 49 và giới hạn số lượng các nhà khai thác mới được giới thiệu, một nhà điều hành postfix, không chính tả

a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
1 đã được đề xuất. Ý tưởng là
a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
1 có thể trả về một đối tượng đặc biệt có thể ghi đè các phương thức Dunder trả về
if a.next is None | a.next.next is None
27. Ví dụ:
if a.next is None | a.next.next is None
28 sẽ đánh giá thành
if a.next is None | a.next.next is None
19 nếu nó không phải là
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, nếu không nó sẽ đánh giá thành một ví dụ là
if a.next is None | a.next.next is None
31:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
1

Với toán tử mới này và loại mới, một biểu thức như

if a.next is None | a.next.next is None
32 đánh giá thành
if a.next is None | a.next.next is None
31 nếu
if a.next is None | a.next.next is None
19 không có. Đây là một khái quát tiện lợi, nhưng nó khó sử dụng trong thực tế vì hầu hết các mã hiện tại đều giành được
if a.next is None | a.next.next is None
31 là gì.

Quay trở lại một trong những ví dụ động lực ở trên, hãy xem xét những điều sau đây:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
2

Bộ tuần tự JSON không biết cách tuần tự hóa

if a.next is None | a.next.next is None
31, cũng như không có API nào khác. Đề xuất này thực sự yêu cầu rất nhiều logic chuyên dụng trong suốt thư viện tiêu chuẩn và bất kỳ thư viện bên thứ ba nào.

Đồng thời, toán tử

a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
1 cũng có thể quá chung chung, theo nghĩa là nó có thể được kết hợp với bất kỳ toán tử nào khác. Những biểu thức sau đây có nghĩa là gì?:too general, in the sense that it can be combined with any other operator. What should the following expressions mean?:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
3

Mức độ khái quát hóa này không hữu ích. Các nhà khai thác thực sự được đề xuất ở đây được giới hạn một cách cố ý ở một vài nhà khai thác dự kiến ​​sẽ giúp việc viết các mẫu mã phổ biến dễ dàng hơn.

Tích hợp a, b = None, None def c(): return None def ex(): raise Exception() (a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3)) (a * b ?? c // d) == a * (b ?? c) // d (a ?? True and b ?? False) == (a ?? True) and (b ?? False) (c() ?? c() ?? True) == True (True ?? ex()) == True (c ?? ex)() == c() 2

Haskell có một khái niệm gọi là có thể gói gọn ý tưởng về giá trị tùy chọn mà không dựa vào bất kỳ từ khóa đặc biệt nào (ví dụ:

a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
3) hoặc bất kỳ trường hợp đặc biệt nào (ví dụ:
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9). Trong Haskell, mục đích của
if a.next is None | a.next.next is None
41 là để tránh xử lý riêng của một thứ gì đó và không có gì.

Một gói Python gọi là Pymaybe cung cấp một xấp xỉ thô. Tài liệu cho thấy ví dụ sau:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
4

Hàm

if a.next is None | a.next.next is None
42 trả về một thể hiện
if a.next is None | a.next.next is None
43 hoặc một thể hiện
if a.next is None | a.next.next is None
44. Tương tự như toán tử postfix unary được mô tả trong phần trước,
if a.next is None | a.next.next is None
44 ghi đè các phương thức Dunder để cho phép xích trên một giá trị bị thiếu.

Lưu ý rằng

if a.next is None | a.next.next is None
46 cuối cùng được yêu cầu để lấy giá trị cơ bản từ các trình bao bọc ____ 247. Hơn nữa,
if a.next is None | a.next.next is None
47 không ngắn mạch bất kỳ đánh giá nào. Mặc dù
if a.next is None | a.next.next is None
47 có một số điểm mạnh và có thể hữu ích theo cách riêng của nó, nhưng nó cũng chứng minh lý do tại sao việc thực hiện Python thuần túy của việc kết hợp không mạnh mẽ như hỗ trợ được xây dựng trong ngôn ngữ.

Ý tưởng thêm một loại

a, b = None, None
def c(): return None
def ex(): raise Exception()

(a ?? 2 ** b ?? 3) == a ?? (2 ** (b ?? 3))
(a * b ?? c // d) == a * (b ?? c) // d
(a ?? True and b ?? False) == (a ?? True) and (b ?? False)
(c() ?? c() ?? True) == True
(True ?? ex()) == True
(c ?? ex)() == c()
2 tích hợp để cho phép kịch bản này bị từ chối.

Chỉ cần sử dụng một biểu thức có điều kiện

Một cách phổ biến khác để khởi tạo các giá trị mặc định là sử dụng toán tử ternary. Dưới đây là một đoạn trích từ gói yêu cầu phổ biến:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
5

Công thức cụ thể này có tác dụng không mong muốn của việc đặt các toán hạng theo thứ tự không trực quan: não nghĩ rằng, sử dụng

if a.next is None | a.next.next is None
51 nếu có thể và sử dụng
if a.next is None or a.next.next is None
92 như một dự phòng, nhưng mã đặt sự thất bại trước giá trị ưu tiên.

Thay vào đó, tác giả của gói này có thể viết nó như thế này:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
6

Thứ tự này của các toán hạng là trực quan hơn, nhưng nó đòi hỏi 4 ký tự bổ sung (cho không phải là không). Nó cũng làm nổi bật sự lặp lại của các định danh:

if a.next is None | a.next.next is None
53,
if a.next is None | a.next.next is None
54, v.v.

Khi được viết bằng cách sử dụng toán tử kết hợp

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
9, mẫu có nội dung:

augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=' | '??=')

power: coalesce ['**' factor]
coalesce: atom_expr ['??' factor]
atom_expr: ['await'] atom trailer*
trailer: ('(' [arglist] ')' |
          '[' subscriptlist ']' |
          '?[' subscriptlist ']' |
          '.' NAME |
          '?.' NAME)
7

Người giới thiệu

Bản quyền

Tài liệu này đã được đặt trong phạm vi công cộng.

Python có sử dụng ||Cho hoặc?

Tương tự như vậy, ||và !không phải là người vận hành python hợp lệ.Vì vậy, thay vào đó, sử dụng hoặc không vận hành.|| and ! are not valid Python operators. So instead, use or and not operator.

Python có đối xử không sai không?

Không giống như trong các ngôn ngữ lập trình khác với các con trỏ null, Python không có đối tượng là một đối tượng hợp lệ.Điều này có nghĩa là nó không phải là 0, sai, hoặc bất cứ điều gì tương tự.Python's None object is a valid object. This means it is not 0, False, or anything like that.

Không có trả về sai?

Không có gì không giống như sai.Không có gì không giống như một chuỗi trống ('').So sánh không có giá trị nào sẽ trả về sai ngoại trừ không có chính nó.Comparing None to any value will return False except None itself.

Hoặc trong Python là gì?

'Hoặc' trong Python là một toán tử logic đánh giá là đúng nếu bất kỳ toán hạng nào là đúng, không giống như toán tử 'và' nơi tất cả các toán hạng phải là đúng.a logical operator that evaluates as True if any of the operands is True, unlike the 'and' operator where all operands have to be True.