Bahwa dua pertanyaan memiliki jawaban yang sama tidak berarti bahwa keduanya merupakan duplikat. Sepele menjawab diri sendiri, tapi tidak sepele melihat alasannya, atau kalau ada jalan keluarnya.
mehmet
Jawaban:
111
Mengapa tidak mencobanya?
>>> defsome_func():... return2... >>> a = 2>>> if (a = some_func()):
File "<stdin>", line 1if (a = some_func()):
^
SyntaxError: invalid syntax
>>>
ini sengaja dilarang karena Guido, diktator python yang baik hati, menganggapnya tidak perlu dan lebih membingungkan daripada berguna. Itu alasan yang sama tidak ada operator pasca-kenaikan atau pra-kenaikan (++).
Matt Boehm
4
dia mengizinkan penambahan tugas tambahan di 2.0 karena x = x + 1membutuhkan waktu pencarian tambahan sementara x += 1itu agak lebih cepat, tapi saya yakin dia bahkan tidak suka melakukan itu . :-)
wescpy
berharap, ini akan segera menjadi mungkin. Python lambat berkembang
Nik O'Lai
4
"mengapa tidak mencobanya" - Karena siapa yang tahu apa sintaksnya? Mungkin OP mencobanya dan tidak berhasil, tetapi itu tidak berarti sintaksnya tidak berbeda, atau tidak ada cara untuk melakukannya yang tidak dimaksudkan
Abstrak
Ini adalah proposal untuk membuat cara untuk menetapkan variabel dalam ekspresi menggunakan notasi NAME: = expr. Pengecualian baru, TargetScopeError ditambahkan, dan ada satu perubahan pada urutan evaluasi.
"Kekacauan PEP 572" adalah topik sesi KTT Bahasa Python 2018 yang dipimpin oleh diktator seumur hidup yang baik hati (BDFL) Guido van Rossum. PEP 572 berupaya untuk menambahkan ekspresi tugas (atau "tugas sebaris") ke bahasa, tetapi telah terjadi diskusi yang berkepanjangan atas beberapa utas besar di milis python-dev — bahkan setelah beberapa putaran pada ide-python. Utas-utas itu sering kali menimbulkan perdebatan dan jelas-jelas sangat banyak sampai-sampai banyak yang mungkin baru saja mengabaikannya. Di KTT tersebut, Van Rossum memberikan gambaran umum tentang proposal fitur, yang tampaknya cenderung dia terima, tetapi dia juga ingin mendiskusikan cara menghindari ledakan benang semacam ini di masa mendatang.
tz hanya digunakan untuk s + = tz, memindahkan tugasnya ke dalam if membantu untuk menunjukkan ruang lingkupnya.
Arus:
s = _format_time(self._hour, self._minute,
self._second, self._microsecond,
timespec)
tz = self._tzstr()
if tz:
s += tz
return s
Peningkatan:
s = _format_time(self._hour, self._minute,
self._second, self._microsecond,
timespec)
if tz := self._tzstr():
s += tz
return s
sysconfig.py Memanggil fp.readline () dalam kondisi while dan memanggil .match () pada baris if membuat kode lebih kompak tanpa
membuatnya lebih sulit untuk dipahami.
Arus:
whileTrue:
line = fp.readline()
ifnot line:
break
m = define_rx.match(line)
if m:
n, v = m.group(1, 2)
try:
v = int(v)
except ValueError:
pass
vars[n] = v
else:
m = undef_rx.match(line)
if m:
vars[m.group(1)] = 0
Peningkatan:
while line := fp.readline():
if m := define_rx.match(line):
n, v = m.group(1, 2)
try:
v = int(v)
except ValueError:
pass
vars[n] = v
elif m := undef_rx.match(line):
vars[m.group(1)] = 0
Menyederhanakan pemahaman daftar Pemahaman daftar dapat memetakan dan memfilter secara efisien dengan menangkap kondisi:
results = [(x, y, x/y) for x in input_data if (y := f(x)) > 0]
Demikian pula, subekspresi dapat digunakan kembali dalam ekspresi utama, dengan memberinya nama pada penggunaan pertama:
stuff = [[y := f(x), x/y] for x in range(5)]
Perhatikan bahwa dalam kedua kasus variabel y terikat dalam ruang lingkup (yaitu pada tingkat yang sama sebagai hasil atau barang).
Menangkap nilai kondisi Ekspresi tugas dapat digunakan untuk memberikan efek yang baik di header pernyataan if atau while:
# Loop-and-a-halfwhile (command := input("> ")) != "quit":
print("You entered:", command)
# Capturing regular expression match objects# See, for instance, Lib/pydoc.py, which uses a multiline spelling# of this effectif match := re.search(pat, text):
print("Found:", match.group(0))
# The same syntax chains nicely into 'elif' statements, unlike the# equivalent using assignment statements.elif match := re.search(otherpat, text):
print("Alternate found:", match.group(0))
elif match := re.search(third, text):
print("Fallback found:", match.group(0))
# Reading socket data until an empty string is returnedwhile data := sock.recv(8192):
print("Received data:", data)
Khususnya dengan while loop, ini bisa menghilangkan kebutuhan untuk memiliki loop tak terbatas, tugas, dan kondisi. Ini juga membuat paralel mulus antara loop yang hanya menggunakan panggilan fungsi sebagai kondisinya, dan yang menggunakannya sebagai kondisinya tetapi juga menggunakan nilai sebenarnya.
Garpu Contoh dari dunia UNIX level rendah:
if pid := os.fork():
# Parent codeelse:
# Child code
Perhatikan bahwa di Python, tidak seperti C, penugasan tidak dapat terjadi di dalam ekspresi. Pemrogram C mungkin mengeluh tentang ini, tetapi ini menghindari kelas umum masalah yang dihadapi dalam program C: mengetik = dalam ekspresi saat == dimaksudkan.
Saya menyukai jawaban ini karena sebenarnya menunjukkan mengapa "fitur" seperti itu mungkin sengaja ditinggalkan dari Python. Saat mengajar pemrograman pemula, saya telah melihat banyak yang membuat kesalahan ini if (foo = 'bar')saat bermaksud menguji nilai foo.
Jonathan Cross
2
@JonathanCross, "Fitur" ini sebenarnya akan ditambahkan di 3.8. Ini tidak mungkin digunakan sesedikit yang seharusnya - tapi setidaknya tidak biasa=
John La Rooy
@JohnLaRooy: Melihat contoh, saya pikir "tidak mungkin digunakan sesering yang seharusnya" sangat tepat; Dari ~ 10 contoh, saya menemukan bahwa hanya dua yang benar-benar meningkatkan kode. (Yaitu, sebagai satu-satunya ekspresi baik dalam kondisi sementara, untuk menghindari duplikasi garis atau kondisi loop di tubuh, atau dalam rantai elif untuk menghindari bersarang)
Aleksi Torhamo
39
Tidak, BDFL tidak menyukai fitur itu.
Dari tempat saya duduk, Guido van Rossum, "Diktator Baik untuk Kehidupan”, telah berjuang keras untuk menjaga agar Python tetap sesederhana mungkin. Kita dapat berdalih dengan beberapa keputusan yang dia buat - saya lebih suka dia berkata 'Tidak 'lebih sering. Tetapi fakta bahwa belum ada komite yang merancang Python, melainkan "dewan penasihat" tepercaya, yang sebagian besar didasarkan pada prestasi, menyaring melalui kepekaan seorang desainer, telah menghasilkan bahasa yang sangat bagus, IMHO.
Sederhana? Fitur ini dapat menyederhanakan beberapa kode saya karena dapat membuatnya lebih kompak dan lebih mudah dibaca. Sekarang saya perlu dua baris yang dulu saya butuhkan. Saya tidak pernah mengerti mengapa Python menolak fitur yang dimiliki bahasa pemrograman lain selama bertahun-tahun (dan seringkali karena alasan yang sangat bagus). Terutama fitur yang kita bicarakan di sini sangat, sangat berguna.
Regis Mei
6
Lebih sedikit kode tidak selalu lebih sederhana atau lebih mudah dibaca. Ambil fungsi rekursif misalnya. Ini setara loop seringkali lebih mudah dibaca.
FMF
1
Saya tidak suka versi C-nya, tetapi saya sangat merindukan memiliki sesuatu seperti karat if letketika saya memiliki rantai if elif, tetapi perlu menyimpan dan menggunakan nilai kondisi di setiap kasus.
Thayne
1
Saya harus mengatakan bahwa kode yang saya tulis sekarang (alasan saya mencari masalah ini) JAUH lebih jelek tanpa fitur ini. Alih-alih menggunakan if diikuti oleh banyak ifs lainnya, saya harus terus mengindentasi if under the last else.
MikeKulls
17
Tidak secara langsung, sesuai resep lama saya ini - tetapi seperti yang dikatakan resep itu mudah untuk membangun padanan semantik, misalnya jika Anda perlu mentransliterasi langsung dari algoritme referensi berkode-C (sebelum melakukan refactoring ke Python yang lebih idiomatik, tentu saja; -). Yaitu:
classDataHolder(object):def__init__(self, value=None): self.value = value
defset(self, value): self.value = value; return value
defget(self):return self.value
data = DataHolder()
while data.set(somefunc()):
a = data.get()
# use a
BTW, bentuk Pythonic yang sangat idiomatik untuk kasus spesifik Anda, jika Anda tahu persis apa nilai palsu yang somefuncdapat dikembalikan ketika mengembalikan nilai yang salah (misalnya 0), adalah
for a in iter(somefunc, 0):
# use a
jadi dalam kasus khusus ini refactoring akan sangat mudah ;-).
Jika pengembalian bisa menjadi salah jenis nilai falsish (0, None, '', ...), salah satu kemungkinan adalah:
import itertools
for a in itertools.takewhile(lambda x: x, iter(somefunc, object())):
# use a
tetapi Anda mungkin lebih suka generator khusus sederhana:
defgetwhile(func, *a, **k):whileTrue:
x = func(*a, **k)
ifnot x: breakyield x
for a in getwhile(somefunc):
# use a
Saya akan memilih ini dua kali jika saya bisa. Ini adalah solusi yang bagus untuk saat-saat ketika sesuatu seperti ini benar-benar dibutuhkan. Saya mengadaptasi solusi Anda ke kelas Matcher regex, yang dibuat sekali dan kemudian .check () digunakan dalam pernyataan if dan .result () digunakan di dalam tubuhnya untuk mengambil kecocokan, jika ada. Terima kasih! :)
Teekin
16
Ya, tetapi hanya dari Python 3.8 dan seterusnya.
PEP 572 mengusulkan Ekspresi Tugas dan telah diterima.
# Handle a matched regexif (match := pattern.search(data)) isnotNone:
# Do something with match# A loop that can't be trivially rewritten using 2-arg iter()while chunk := file.read(8192):
process(chunk)
# Reuse a value that's expensive to compute
[y := f(x), y**2, y**3]
# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) isnotNone]
Dan Guido tidak akan melakukannya dengan cara lain.
Mark Ransom
1
@ MarkRans Semua hail Guido. Benar .. menghela napas.
StephenBoesch
@javadba pria itu lebih sering benar daripada dia salah. Saya menghargai bahwa memiliki satu orang yang bertanggung jawab atas visi menghasilkan strategi yang jauh lebih koheren daripada desain oleh komite; Saya dapat membandingkan dan membedakan dengan C ++ yang merupakan roti dan mentega utama saya.
Mark Ransom
Saya merasa baik ruby dan scala (v bahasa yang berbeda) melakukannya dengan benar secara signifikan lebih dari python: tetapi bagaimanapun juga di sini bukanlah tempatnya ..
StephenBoesch
4
Berkat fitur baru Python 3.8, Anda dapat melakukan hal seperti itu dari versi ini, meskipun tidak menggunakan =tetapi operator penugasan seperti Ada :=. Contoh dari dokumen:
# Handle a matched regexif (match := pattern.search(data)) isnotNone:
# Do something with match
Salah satu alasan mengapa penetapan ilegal dalam kondisi adalah karena lebih mudah membuat kesalahan dan menetapkan Benar atau Salah:
some_variable = 5# This does not work# if True = some_variable:# do_something()# This only works in Python 2.xTrue = some_variable
printTrue# returns 5
Di Python 3 True dan False adalah kata kunci, jadi tidak ada resiko lagi.
Jawaban:
Mengapa tidak mencobanya?
>>> def some_func(): ... return 2 ... >>> a = 2 >>> if (a = some_func()): File "<stdin>", line 1 if (a = some_func()): ^ SyntaxError: invalid syntax >>>
Jadi tidak.
Pembaruan: Ini dimungkinkan (dengan sintaks berbeda) dengan Python 3.8
sumber
x = x + 1
membutuhkan waktu pencarian tambahan sementarax += 1
itu agak lebih cepat, tapi saya yakin dia bahkan tidak suka melakukan itu . :-)UPDATE - Jawaban asli ada di dekat bagian bawah
Python 3.8 akan membawa PEP572
https://lwn.net/Articles/757713/
https://www.python.org/dev/peps/pep-0572/#examples-from-the-python-standard-library
Jawaban asli
http://docs.python.org/tutorial/datastructures.html
lihat juga:
http://effbot.org/pyfaq/why-can-ti-use-an-assignment-in-an-expression.htm
sumber
if (foo = 'bar')
saat bermaksud menguji nilaifoo
.=
Tidak, BDFL tidak menyukai fitur itu.
Dari tempat saya duduk, Guido van Rossum, "Diktator Baik untuk Kehidupan”, telah berjuang keras untuk menjaga agar Python tetap sesederhana mungkin. Kita dapat berdalih dengan beberapa keputusan yang dia buat - saya lebih suka dia berkata 'Tidak 'lebih sering. Tetapi fakta bahwa belum ada komite yang merancang Python, melainkan "dewan penasihat" tepercaya, yang sebagian besar didasarkan pada prestasi, menyaring melalui kepekaan seorang desainer, telah menghasilkan bahasa yang sangat bagus, IMHO.
sumber
if let
ketika saya memiliki rantai if elif, tetapi perlu menyimpan dan menggunakan nilai kondisi di setiap kasus.Tidak secara langsung, sesuai resep lama saya ini - tetapi seperti yang dikatakan resep itu mudah untuk membangun padanan semantik, misalnya jika Anda perlu mentransliterasi langsung dari algoritme referensi berkode-C (sebelum melakukan refactoring ke Python yang lebih idiomatik, tentu saja; -). Yaitu:
class DataHolder(object): def __init__(self, value=None): self.value = value def set(self, value): self.value = value; return value def get(self): return self.value data = DataHolder() while data.set(somefunc()): a = data.get() # use a
BTW, bentuk Pythonic yang sangat idiomatik untuk kasus spesifik Anda, jika Anda tahu persis apa nilai palsu yang
somefunc
dapat dikembalikan ketika mengembalikan nilai yang salah (misalnya0
), adalahfor a in iter(somefunc, 0): # use a
jadi dalam kasus khusus ini refactoring akan sangat mudah ;-).
Jika pengembalian bisa menjadi salah jenis nilai falsish (0,
None
,''
, ...), salah satu kemungkinan adalah:import itertools for a in itertools.takewhile(lambda x: x, iter(somefunc, object())): # use a
tetapi Anda mungkin lebih suka generator khusus sederhana:
def getwhile(func, *a, **k): while True: x = func(*a, **k) if not x: break yield x for a in getwhile(somefunc): # use a
sumber
Ya, tetapi hanya dari Python 3.8 dan seterusnya.
PEP 572 mengusulkan Ekspresi Tugas dan telah diterima.
Mengutip bagian Sintaks dan semantik dari PEP:
# Handle a matched regex if (match := pattern.search(data)) is not None: # Do something with match # A loop that can't be trivially rewritten using 2-arg iter() while chunk := file.read(8192): process(chunk) # Reuse a value that's expensive to compute [y := f(x), y**2, y**3] # Share a subexpression between a comprehension filter clause and its output filtered_data = [y for x in data if (y := f(x)) is not None]
Dalam kasus khusus Anda, Anda akan bisa menulis
if a := some_func(): # Use a
sumber
Tidak. Tugas dengan Python adalah pernyataan, bukan ekspresi.
sumber
Berkat fitur baru Python 3.8, Anda dapat melakukan hal seperti itu dari versi ini, meskipun tidak menggunakan
=
tetapi operator penugasan seperti Ada:=
. Contoh dari dokumen:# Handle a matched regex if (match := pattern.search(data)) is not None: # Do something with match
sumber
Anda dapat menentukan fungsi untuk melakukan penugasan untuk Anda:
def assign(name, value): import inspect frame = inspect.currentframe() try: locals_ = frame.f_back.f_locals finally: del frame locals_[name] = value return value if assign('test', 0): print("first", test) elif assign('xyz', 123): print("second", xyz)
sumber
Salah satu alasan mengapa penetapan ilegal dalam kondisi adalah karena lebih mudah membuat kesalahan dan menetapkan Benar atau Salah:
some_variable = 5 # This does not work # if True = some_variable: # do_something() # This only works in Python 2.x True = some_variable print True # returns 5
Di Python 3 True dan False adalah kata kunci, jadi tidak ada resiko lagi.
sumber
== True
di sisi kanan.Operator penugasan - juga dikenal secara informal sebagai operator walrus - dibuat pada 28-Feb-2018 di PEP572 .
Demi kelengkapan, saya akan memposting bagian-bagian yang relevan sehingga Anda dapat membandingkan perbedaan antara 3.7 dan 3.8:
3.7 --- if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond lambdef: 'lambda' [varargslist] ':' test lambdef_nocond: 'lambda' [varargslist] ':' test_nocond or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* 3.8 --- if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite] namedexpr_test: test [':=' test] <---- WALRUS OPERATOR!!! test: or_test ['if' or_test 'else' test] | lambdef or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)*
sumber