Saya menulis sebuah fungsi:

# given a n x m grid return how many different ways there are to move from top left to 
# bottom right by only being able to move right or down

def grid(n, m, memo = {}):
    if f'{n},{m}' in memo:
        return memo[f'{n},{m}']

    if n == 1 and m == 1:
        return 1
    
    if n == 0 or m == 0:
        return 0

    memo[f'{n},{m}'] = grid(n,m-1,) + grid(n-1,m)

    return grid(n,m-1,) + grid(n-1,m)

Baru-baru ini saya membaca sedikit tentang hubungan arus pendek dengan Python dan saya mencoba untuk memahaminya lebih jauh.

Seperti yang saya pahami, itu tidak memberikan dorongan apa pun dalam runtime, hanya semacam gula sintaksis.

Sebagai contoh:

1 < 2 < 3 # is True
1 < 2 and 2 < 3 # is also True

# hence
(1 < 2 < 3) == 1 < 2 and 2 < 3 # is True

Saya bertanya-tanya dapatkah saya menulis fungsi saya dengan hubungan arus pendek semacam ini dalam pernyataan if saya?

Saya datang dengan ini:

 def grid(n, m, memo = {}):
    if f'{n},{m}' in memo:
        return memo[f'{n},{m}']

    if (n or m) == 1:
        return 1
    
    if (n and m) == 0:
        return 0

    memo[f'{n},{m}'] = grid(n,m-1,) + grid(n-1,m)

    return grid(n,m-1,) + grid(n-1,m)

Apakah ada cara yang lebih cerdas untuk menggunakan korsleting di sini?

0
Jonas Palačionis 4 Januari 2021, 20:44

3 jawaban

Jawaban Terbaik

if (n or m) == 1 jelas tidak sama dengan if n == 1 or m == 1. Pernyataan if pertama setara dengan:

value = n
if not value:
    value = m
if value == 1:
    # do something:

Atau diungkapkan lebih ringkas:

if (n if n else m) == 1:
       # do something

Dengan kata lain, n or m hanya mengevaluasi m jika n Salah (atau 0 jika n adalah bilangan bulat), jika tidak, hasil ekspresinya adalah n .

Yang ingin Anda hindari redundansi adalah:

if 1 in (n, m): # equivalent to: if 1 is either n or m:

Pembaruan: Demo

n = 4
m = 1
if (n or m) == 1:
    print('if branch taken')
else:
    print('else branch taken')

Cetakan:

else branch taken
1
Booboo 4 Januari 2021, 18:21

(1 < 2 < 3) bukan hubungan arus pendek - saya rasa Anda salah memahami arti istilah tersebut. Anda benar bahwa itu hanyalah gula sintaksis - meskipun itu dapat menghasilkan beberapa hasil yang sangat aneh dalam kasus-kasus yang tidak jelas. (1 < 2 < 3) diperluas ke (1 < 2) and (2 < 3) - operan tengah disalin ke keduanya dan and digunakan untuk operator gabungan.

Hubungan arus pendek terjadi ketika python sudah tahu jawaban untuk ekspresi boolean, bahkan sebelum menghitung kedua input. Sebagai contoh

def false():
    print("false")
    return False

def true():
    print("true")
    return True

print(false() and true())

Outputnya adalah

false
False

Karena ketika python melihat False and, ia sudah tahu bahwa hasilnya adalah False (karena and membutuhkan kedua operan menjadi True), jadi tidak repot menjalankan yang kedua setengah dari garis. Hubungan arus pendek yang sebenarnya ini memang menghasilkan peningkatan kinerja, tetapi karena Anda tidak dapat mematikan hubungan arus pendek, itu tidak masalah ¯\_(ツ)_/¯

3
wjandrea 4 Januari 2021, 18:59
if (n or m) == 1

Mengevaluasi untuk

if (<bool>) == 1  # e.g. if {True,False} == 1

Yang mungkin bukan yang Anda inginkan, karena pada dasarnya mengevaluasi kebenaran n atau m.

Kode Anda yang ada sudah menangkap sifatnya hubungan arus pendek;

if n == 1 and m == 1

Hanya akan mengevaluasi argumen kedua m == 1 iff n == 1, atau sebaliknya akan mengalami hubungan pendek.

Untuk komentar Anda

Seperti yang saya pahami, itu tidak memberikan dorongan apa pun dalam runtime, hanya semacam sintaksis gula.

Yah, sebenarnya itu memberikan dorongan runtime jika Python dapat melewati evaluasi apa yang seharusnya menjadi kondisi "mahal" untuk dievaluasi karena ia dapat mengalami hubungan pendek lebih awal.

1
Brad Solomon 4 Januari 2021, 17:49