Fitur tersembunyi dari Python [ditutup]

1419

Apa saja fitur yang kurang diketahui tetapi berguna dari bahasa pemrograman Python?

  • Cobalah untuk membatasi jawaban ke inti Python.
  • Satu fitur per jawaban.
  • Berikan contoh dan deskripsi singkat tentang fitur ini, bukan hanya tautan ke dokumentasi.
  • Beri label fitur menggunakan judul sebagai baris pertama.

Tautan cepat ke jawaban:

compie
sumber

Jawaban:

740

Operator perbandingan operator:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

Jika Anda berpikir sedang melakukan 1 < x, yang keluar sebagai True, dan kemudian membandingkan True < 10, yang juga True, maka tidak, itu benar-benar bukan yang terjadi (lihat contoh terakhir.) Ini benar-benar diterjemahkan ke dalam 1 < x and x < 10, dan x < 10 and 10 < x * 10 and x*10 < 100, tetapi dengan kurang mengetik dan masing-masing Istilah ini hanya dievaluasi sekali.

Thomas Wouters
sumber
121
Itu sangat membantu. Itu harus standar untuk semua bahasa. Sayangnya, tidak.
stalepretzel
8
Anda harus menambahkan beberapa contoh yang mengembalikan false juga. seperti >>> 10 <x <20 Salah
ShoeLace
19
Ini juga berlaku untuk operator pembanding lainnya, itulah sebabnya orang terkadang terkejut mengapa kode seperti (5 in [5] Benar) adalah False (tetapi tidak etis untuk secara eksplisit menguji terhadap boolean seperti itu untuk memulainya).
Miles
19
Bagus tapi hati-hati dengan presedensi yang sama, seperti 'dalam' dan '='. 'A dalam B == C dalam D' berarti '(A dalam B) dan (B == C) dan (C dalam D)' yang mungkin tidak terduga.
Charles Merriam
15
Azafe: Perbandingan Lisp secara alami bekerja seperti ini. Ini bukan kasus khusus karena tidak ada cara lain (masuk akal) untuk menafsirkan (< 1 x 10). Anda bahkan dapat menerapkannya pada argumen tunggal, seperti (= 10): cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/…
Ken
512

Dapatkan pohon parse regex python untuk men-debug regex Anda.

Ekspresi reguler adalah fitur hebat dari python, tetapi men-debug-nya bisa sangat menyebalkan, dan terlalu mudah untuk membuat kesalahan regex.

Untungnya, python dapat mencetak pohon parse regex, dengan melewatkan flag yang tidak didokumentasikan, eksperimental, dan disembunyikan re.DEBUG(sebenarnya, 128) ke re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Setelah Anda memahami sintaks, Anda dapat menemukan kesalahan Anda. Di sana kita bisa melihat bahwa saya lupa untuk melarikan diri []di [/font].

Tentu saja Anda dapat menggabungkannya dengan bendera apa pun yang Anda inginkan, seperti regex yang dikomentari:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)
BatchyX
sumber
3
Kecuali parsing HTML menggunakan ekspresi reguler lambat dan menyakitkan. Bahkan modul parser 'html' bawaan tidak menggunakan regex untuk menyelesaikan pekerjaan. Dan jika modul html tidak menyenangkan Anda, ada banyak modul parser XML / HTML yang melakukan pekerjaan tanpa harus menemukan kembali roda.
BatchyX
Tautan ke dokumentasi pada sintaks keluaran akan sangat bagus.
Personman
1
Ini harus menjadi bagian resmi dari Python, bukan eksperimental ... RegEx selalu rumit dan mampu melacak apa yang terjadi sangat membantu.
Cahit
460

menghitung

Bungkus iterable dengan enumerate dan itu akan menghasilkan item beserta indeksnya.

Sebagai contoh:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Referensi:

Dave
sumber
56
Saya terkejut ini tidak dibahas secara rutin dalam tutorial berbicara tentang daftar python.
Draemon
45
Dan selama ini saya mengkode dengan cara ini: untuk i dalam range (len (a)): ... dan kemudian menggunakan [i] untuk mendapatkan item saat ini.
Fernando Martin
4
@Berry Tsakala: Setahu saya, itu belum ditinggalkan.
JAB
23
Omong kosong, ini luar biasa. untuk saya di xrange (len (a)): selalu menjadi idiom python favorit saya
Personman
15
enumerate dapat mulai dari indeks arbitrer, tidak perlu 0. Contoh: 'untuk i, item dalam enumerate ( daftar , mulai = 1): cetak i, item' akan memulai enumerasi dari 1, bukan 0.
dmitry_romanov
419

Membuat objek generator

Jika kamu menulis

x=(n for n in foo if bar(n))

Anda bisa mengeluarkan generator dan menugaskannya ke x. Sekarang berarti Anda bisa melakukannya

for n in x:

Keuntungan dari hal ini adalah Anda tidak perlu penyimpanan perantara, yang akan Anda perlukan jika memang perlu

x = [n for n in foo if bar(n)]

Dalam beberapa kasus, ini dapat mempercepat secara signifikan.

Anda dapat menambahkan banyak pernyataan if ke akhir generator, yang pada dasarnya mereplikasi nested for loop:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)
freespace
sumber
Anda juga bisa menggunakan pemahaman daftar bersarang untuk itu, ya?
shapr
54
Dari catatan khusus adalah penghematan overhead memori. Nilai dihitung berdasarkan permintaan, sehingga Anda tidak pernah memiliki seluruh hasil dari pemahaman daftar dalam memori. Ini sangat diinginkan jika Anda kemudian beralih hanya pada sebagian dari pemahaman daftar.
saffsd
19
Ini bukan imo "tersembunyi", tetapi juga patut dicatat adalah kenyataan bahwa Anda tidak dapat memundurkan objek generator, sedangkan Anda dapat mengulangi daftar beberapa kali.
Susmits
13
Fitur "no rewind" generator dapat menyebabkan kebingungan. Khususnya, jika Anda mencetak konten generator untuk debugging, kemudian menggunakannya nanti untuk memproses data, itu tidak berfungsi. Data diproduksi, dikonsumsi oleh cetak (), maka tidak tersedia untuk pemrosesan normal. Ini tidak berlaku untuk pemahaman daftar, karena mereka benar-benar disimpan dalam memori.
johntellsall
4
Jawaban (dup?) Yang serupa: stackoverflow.com/questions/101268/hidden-features-of-python/… . Namun, perhatikan bahwa jawaban yang saya tautkan di sini menyebutkan presentasi yang BENAR-BENAR BAIK tentang kekuatan generator. Anda benar-benar harus memeriksanya.
Denilson Sá Maia
353

iter () dapat mengambil argumen yang bisa dipanggil

Contohnya:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

The iter(callable, until_value)fungsi berulang kali memanggil callabledan menghasilkan hasilnya sampai until_valuedikembalikan.

mbac32768
sumber
Sebagai pemula untuk python, dapatkah Anda menjelaskan mengapa lambdakata kunci diperlukan di sini?
SiegeX
@ SiegeX tanpa lambda, f.read (1) akan dievaluasi (mengembalikan string) sebelum diteruskan ke fungsi iter. Sebaliknya, lambda menciptakan fungsi anonim dan meneruskannya ke iter.
jmilloy
339

Hati-hati dengan argumen default yang bisa berubah

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Alih-alih, Anda harus menggunakan nilai sentinel yang menunjukkan "tidak diberikan" dan ganti dengan yang dapat diubah yang Anda inginkan sebagai default:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]
Jason Baker
sumber
39
Itu pasti salah satu fitur tersembunyi yang lebih buruk. Saya telah mengalami hal itu dari waktu ke waktu.
Torsten Marek
77
Saya menemukan ini jauh lebih mudah untuk dipahami ketika saya mengetahui bahwa argumen default hidup dalam sebuah tuple yang merupakan atribut dari fungsi, misalnya foo.func_defaults. Yang, sebagai tuple, tidak berubah.
Robert Rossney
2
@ grayger: Ketika pernyataan def dieksekusi argumennya dievaluasi oleh penerjemah. Ini membuat (atau rebind) nama ke objek kode (paket fungsi). Namun, argumen default dipakai sebagai objek pada saat definisi. Ini berlaku untuk setiap saat objek default, tetapi hanya signifikan (mengekspos semantik yang terlihat) ketika objek tersebut bisa berubah. Tidak ada cara untuk mengikat kembali nama argumen default dalam penutupan fungsi meskipun jelas dapat ditunggangi untuk panggilan apa pun atau seluruh fungsi dapat didefinisikan ulang).
Jim Dennis
3
@ Robert tentu saja argumen tuple mungkin tidak berubah, tetapi objek yang dituju tidak selalu abadi.
poolie
16
Satu retasan cepat untuk membuat inisialisasi Anda sedikit lebih pendek: x = x atau []. Anda dapat menggunakannya sebagai ganti pernyataan 2 baris jika.
dave mankoff
317

Mengirim nilai ke fungsi generator . Misalnya memiliki fungsi ini:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

Kamu bisa:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7
Rafał Dowgird
sumber
Sepakat. Mari kita memperlakukan ini sebagai contoh buruk dari fitur tersembunyi Python :)
Rafał Dowgird
89
Dalam bahasa lain, saya percaya perangkat ajaib ini disebut "variabel".
finnw
5
coroutine haruslah coroutine dan genenerator juga harus menjadi dirinya sendiri, tanpa pencampuran. Tautan hebat dan obrolan dan contoh tentang ini di sini: dabeaz.com/coroutines
u0b34a0f6ae
31
@finnw: contoh mengimplementasikan sesuatu yang mirip dengan variabel. Namun, fitur tersebut dapat digunakan dengan banyak cara lain ... tidak seperti variabel. Harus juga jelas bahwa semantik serupa dapat diimplementasikan menggunakan objek ( khususnya metode panggilan kelas Python , khususnya).
Jim Dennis
4
Ini terlalu sepele contoh bagi orang yang belum pernah melihat (dan mungkin tidak akan mengerti) ko-rutinitas. Contoh yang mengimplementasikan rata-rata berjalan tanpa risiko jumlah variabel overflow adalah yang baik.
Prashant Kumar
313

Jika Anda tidak suka menggunakan spasi untuk menunjukkan cakupan, Anda dapat menggunakan gaya-C {} dengan mengeluarkan:

from __future__ import braces
bengkak
sumber
122
Itu jahat. :)
Jason Baker
37
>>> dari __future__ import braces File "<stdin>", baris 1 Sintaks: tidak ada peluang: P
Benjamin W. Smith
40
itu penistaan!
Berk D. Demir
335
Saya pikir kita mungkin memiliki kesalahan sintaksis di sini, bukankah seharusnya "dari __past__ import braces"?
Bill K
47
dari __cruft__ kawat gigi impor
Phillip B Oldham
305

Argumen langkah dalam operator slice. Sebagai contoh:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

Kasus khusus x[::-1]adalah ungkapan yang berguna untuk 'x terbalik'.

>>> a[::-1]
[5,4,3,2,1]
Rafał Dowgird
sumber
31
jauh lebih jelas, menurut saya, adalah fungsi terbalik (). >>> daftar (terbalik (kisaran (4))) [3, 2, 1, 0]
Christian Oudard
3
lalu bagaimana menulis "ini ia string" [:: - 1] dengan cara yang lebih baik? terbalik sepertinya tidak membantu
Berry Tsakala
24
Masalah dengan reversed () adalah ia mengembalikan iterator, jadi jika Anda ingin mempertahankan jenis urutan terbalik (tuple, string, list, unicode, jenis pengguna ...), Anda memerlukan langkah tambahan untuk mengubahnya kembali .
Rafał Dowgird
6
def reverse_string (string): return string [:: - 1]
pi.
4
@ pi Saya pikir jika seseorang cukup tahu untuk mendefinisikan reverse_string seperti yang Anda miliki maka seseorang dapat meninggalkan [:: - 1] dalam kode Anda dan merasa nyaman dengan artinya dan merasa itu sesuai.
physicsmichael
289

Dekorator

Dekorator memungkinkan untuk membungkus fungsi atau metode dalam fungsi lain yang dapat menambah fungsionalitas, memodifikasi argumen atau hasil, dll. Anda menulis dekorator satu baris di atas definisi fungsi, dimulai dengan tanda "at" (@).

Contoh menunjukkan print_argsdekorator yang mencetak argumen fungsi yang didekorasi sebelum memanggilnya:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo
DzinX
sumber
54
Ketika mendefinisikan dekorator, saya akan merekomendasikan mendekorasi dekorator dengan @decorator. Ini menciptakan dekorator yang mempertahankan fungsi tanda tangan ketika melakukan introspeksi padanya. Info lebih lanjut di sini: phyast.pitt.edu/~micheles/python/documentation.html
sirwart
45
Bagaimana ini fitur tersembunyi?
Vetle
50
Yah, itu tidak ada dalam tutorial Python paling sederhana, dan saya menemukan itu lama setelah saya mulai menggunakan Python. Itulah yang saya sebut sebagai fitur tersembunyi, hampir sama dengan posting teratas lainnya di sini.
DzinX
16
Vetler, pertanyaannya menanyakan "fitur yang kurang diketahui tetapi berguna dari bahasa pemrograman Python." Bagaimana Anda mengukur 'fitur yang kurang dikenal tetapi bermanfaat'? Maksud saya, bagaimana salah satu dari respons ini menyembunyikan fitur?
Johnd
4
@vetler Sebagian besar hal di sini hampir tidak "disembunyikan".
Humphrey Bogart
288

Sintaks untuk ... else (lihat http://docs.python.org/ref/for.html )

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

Blok "lain" biasanya akan dieksekusi pada akhir dari for loop, kecuali jika break disebut.

Kode di atas dapat ditiru sebagai berikut:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")
rlerallut
sumber
218
Saya pikir sintaks for / else canggung. "Rasanya" seolah-olah klausa lain harus dieksekusi jika tubuh loop tidak pernah dieksekusi.
codeape
14
ah. Belum pernah melihatnya! Tapi saya harus mengatakan itu agak keliru. Siapa yang akan mengharapkan blok lain dieksekusi hanya jika break tidak pernah terjadi? Saya setuju dengan codeape: Sepertinya ada yang masuk untuk foos kosong.
Daren Thomas
52
Sepertinya kata kunci harus akhirnya, bukan yang lain
Jiaaro
21
Kecuali akhirnya sudah digunakan dengan cara di mana suite itu selalu dieksekusi.
7
Seharusnya tidak menjadi 'lain'. Mungkin 'dulu' atau sesuatu, dan kemudian 'lain' ketika loop tidak pernah dieksekusi.
Tor Valamo
258

Dari 2,5 dan seterusnya dikte memiliki metode khusus __missing__yang dipanggil untuk item yang hilang:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Ada juga subkelas dict yang collectionsdisebutnya defaultdictyang melakukan hampir sama tetapi memanggil fungsi tanpa argumen untuk item yang tidak ada:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Saya sarankan untuk mengubah dikte tersebut menjadi dikte biasa sebelum meneruskannya ke fungsi yang tidak diharapkan subkelas tersebut. Banyak kode menggunakan d[a_key]dan menangkap KeyErrors untuk memeriksa apakah ada item yang akan menambahkan item baru ke dikt.

Armin Ronacher
sumber
10
Saya lebih suka menggunakan setdefault. m = {}; m.setdefault ('foo', 1)
grayger
22
@ Grayger berarti ini m={}; m.setdefault('foo', []).append(1).
Cristian Ciupitu
1
Namun ada kasus di mana melewati defaultdict sangat berguna. Fungsi tersebut misalnya, mungkin lebih dari nilai dan berfungsi untuk kunci yang tidak ditentukan tanpa kode tambahan, karena standarnya adalah daftar kosong.
Marian
3
defaultdict lebih baik dalam beberapa keadaan daripada setdefault, karena tidak membuat objek default kecuali kunci hilang. setdefault membuatnya apakah hilang atau tidak. Jika objek default Anda mahal untuk dibuat, ini bisa menjadi hit kinerja - Saya mendapat speedup yang layak dari satu program hanya dengan mengubah semua panggilan setdefault.
Whatang
2
defaultdictjuga lebih kuat daripada setdefaultmetode dalam kasus lain. Sebagai contoh, untuk kontra dd = collections.defaultdict(int) ... dd[k] += 1vs d.setdefault(k, 0) += 1.
Mike Graham
247

Penukaran nilai di tempat

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

Sisi kanan penugasan adalah ekspresi yang membuat tuple baru. Sisi kiri penugasan segera membongkar bahwa (tidak direferensikan) tuple ke nama adan b.

Setelah penugasan, tuple baru tidak direferensikan dan ditandai untuk pengumpulan sampah, dan nilai-nilai terikat adan btelah ditukar.

Seperti yang disebutkan di bagian tutorial Python tentang struktur data ,

Perhatikan bahwa banyak tugas benar-benar hanya kombinasi dari pengemasan tuple dan urutan pembongkaran.

Lucas S.
sumber
1
Apakah ini menggunakan lebih banyak memori nyata daripada cara tradisional? Saya kira lakukan karena Anda membuat tuple, bukan hanya satu variabel swap
Nathan
75
Itu tidak menggunakan lebih banyak memori. Ini menggunakan lebih sedikit .. Saya hanya menulis dua-duanya, dan de-kompilasi bytecode .. kompiler mengoptimalkan, seperti yang Anda harapkan. hasil dis menunjukkan sedang menyiapkan vars, dan kemudian ROT_TWOing. ROT_TWO berarti 'menukar dua stack stack paling atas' ... Cukup manis, sebenarnya.
kerajaan
5
Anda juga secara tidak sengaja menunjukkan fitur bagus lain dari Python, yaitu Anda dapat secara implisit membuat tupel item hanya dengan memisahkannya dengan koma.
asmeurer
3
Dana the Sane: penugasan dalam Python adalah pernyataan, bukan ekspresi, sehingga ekspresi tidak valid jika = memiliki prioritas lebih tinggi (yaitu ditafsirkan sebagai, (b = b), a).
hbn
5
Ini adalah fitur paling tersembunyi yang pernah saya baca di sini. Bagus, tetapi dijelaskan secara eksplisit di setiap tutorial Python.
Thiago Chaves
235

Ekspresi reguler yang dapat dibaca

Dengan Python Anda dapat membagi ekspresi reguler menjadi beberapa baris, beri nama kecocokan Anda dan masukkan komentar.

Contoh sintaksis verbose (dari Menyelam ke Python ):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

Contoh penamaan yang cocok (dari Regular Expression HOWTO )

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

Anda juga dapat secara tertulis menulis regex tanpa menggunakan re.VERBOSEterima kasih kepada string literal.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"
pengguna18044
sumber
7
Saya tidak tahu apakah saya benar-benar mempertimbangkan fitur Python, kebanyakan mesin RE memiliki opsi verbose.
Jeremy Banks
18
Ya, tetapi karena Anda tidak dapat melakukannya di grep atau di sebagian besar editor, banyak orang tidak tahu itu ada di sana. Fakta bahwa bahasa lain memiliki fitur yang setara tidak membuatnya menjadi fitur python yang bermanfaat dan sedikit diketahui
Mark Baker
7
Dalam sebuah proyek besar dengan banyak ekspresi reguler yang dioptimalkan (baca: dioptimalkan untuk mesin tetapi tidak untuk manusia), saya menggigit peluru dan mengubah semuanya menjadi sintaksis verbose. Sekarang, memperkenalkan pengembang baru ke proyek jauh lebih mudah. Mulai sekarang kami memberlakukan RE verbose di setiap proyek.
Berk D. Demir
Saya lebih suka mengatakan: ratusan = "(CM | CD | D? C {0,3})" # 900 (CM), 400 (CD), dll. Bahasa ini sudah memiliki cara untuk memberi nama benda, a cara untuk menambahkan komentar, dan cara untuk menggabungkan string. Mengapa menggunakan sintaksis perpustakaan khusus di sini untuk hal-hal yang sudah dilakukan bahasa dengan sangat baik? Tampaknya langsung melawan Perlis 'Epigram 9.
Ken
3
@ Ken: regex mungkin tidak selalu langsung di sumbernya, bisa dibaca dari pengaturan atau file konfigurasi. Mengizinkan komentar atau hanya spasi putih tambahan (agar mudah dibaca) dapat sangat membantu.
222

Argumen fungsi membongkar

Anda dapat membongkar daftar atau kamus sebagai argumen fungsi menggunakan *dan **.

Sebagai contoh:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Jalan pintas yang sangat berguna karena daftar, tupel dan dikte banyak digunakan sebagai wadah.

e-satis
sumber
27
* juga dikenal sebagai operator percikan
Gabriel
3
Saya suka fitur ini, tetapi pylint tidak sedih.
Stephen Paulger
5
saran pylint bukan hukum. Cara lain, berlaku (callable, arg_seq, arg_map), sudah tidak digunakan lagi sejak 2.3.
Yann Vernier
1
nasihat pylint mungkin bukan hukum, tetapi nasihat yang sangat bagus. Kode debug yang terlalu memanjakan diri dalam hal-hal seperti ini adalah neraka murni. Seperti dicatat oleh poster aslinya, ini adalah jalan pintas yang bermanfaat .
Andrew
2
Saya melihat ini digunakan dalam kode sekali dan bertanya-tanya apa fungsinya. Sayangnya sulit untuk google untuk "Python **"
Fraser Graham
205

ROT13 adalah pengodean yang valid untuk kode sumber, ketika Anda menggunakan deklarasi pengkodean yang tepat di bagian atas file kode:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
André
sumber
10
Bagus! Perhatikan bagaimana string byte diambil secara harfiah, tapi string unicode yang diterjemahkan: trycevag h"Uryyb fgnpxbiresybj!"
u0b34a0f6ae
12
Sayangnya itu dihapus dari py3k
mykhal
9
Ini bagus untuk mem-bypass antivirus.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
96
Itu tidak ada hubungannya dengan pengkodean, itu hanya Python yang ditulis dalam bahasa Welsh. :-P
Olivier Verdier
33
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
Manuel Ferreria
183

Membuat tipe baru dengan cara yang sepenuhnya dinamis

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

yang persis sama dengan

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

Mungkin bukan hal yang paling berguna, tapi menyenangkan untuk diketahui.

Sunting : Nama tetap tipe baru, harus NewTypesama persis dengan classpernyataan.

Sunting : Menyesuaikan judul untuk menjelaskan fitur dengan lebih akurat.

Torsten Marek
sumber
8
Ini memiliki banyak potensi untuk kegunaan, misalnya, JIT ORM
Mark Cidade
8
Saya menggunakannya untuk menghasilkan kelas-kelas HTML-Form berdasarkan input dinamis. Sangat bagus!
pi.
15
Catatan: semua kelas dibuat saat runtime. Jadi, Anda dapat menggunakan pernyataan 'kelas' dalam kondisi, atau dalam suatu fungsi (sangat berguna untuk membuat keluarga kelas atau kelas yang bertindak sebagai penutup). Peningkatan yang dibawa 'tipe' adalah kemampuan untuk mendefinisikan dengan rapi seperangkat atribut (atau pangkalan) yang dihasilkan secara dinamis.
spookylukey
1
Anda juga dapat membuat tipe anonim dengan string kosong seperti: type ('', (object,), {'x': 'blah'})
bluehavana
3
Bisa jadi sangat berguna untuk injeksi kode.
Avihu Turzion
179

Manajer konteks dan pernyataan " with"

Diperkenalkan dalam PEP 343 , manajer konteks adalah objek yang bertindak sebagai konteks run-time untuk serangkaian pernyataan.

Karena fitur ini menggunakan kata kunci baru, diperkenalkan secara bertahap: ini tersedia dalam Python 2.5 melalui __future__arahan. Python 2.6 dan di atasnya (termasuk Python 3) telah tersedia secara default.

Saya sering menggunakan pernyataan "with" karena saya pikir ini adalah konstruk yang sangat berguna, berikut adalah demo singkatnya:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

Apa yang terjadi di sini di belakang layar, adalah bahwa pernyataan "with" memanggil spesial__enter__ dan __exit__pada objek file. Detail pengecualian juga diteruskan ke __exit__jika ada pengecualian yang diajukan dari badan pernyataan with, yang memungkinkan penanganan pengecualian terjadi di sana.

Apa yang ini lakukan untuk Anda dalam kasus khusus ini adalah bahwa ia menjamin bahwa file ditutup ketika eksekusi keluar dari ruang lingkup with suite, terlepas dari apakah itu terjadi secara normal atau apakah pengecualian dilemparkan. Ini pada dasarnya adalah cara untuk mengabstraksi kode penanganan pengecualian yang umum.

Kasing penggunaan umum lainnya untuk ini termasuk penguncian dengan utas dan transaksi basis data.

Ycros
sumber
3
Saya tidak akan menyetujui peninjauan kode yang mengimpor apa pun dari masa depan . Fitur-fiturnya lebih lucu daripada berguna, dan biasanya mereka hanya membingungkan pendatang baru Python.
nerd yang dibayar
6
Ya, fitur "imut" seperti lingkup bersarang dan generator lebih baik diserahkan kepada mereka yang tahu apa yang mereka lakukan. Dan siapa pun yang ingin kompatibel dengan versi Python di masa depan. Untuk cakupan dan generator bersarang, "versi masa depan" dari Python berarti masing-masing 2.2 dan 2.5. Untuk pernyataan with, "versi masa depan" dari Python berarti 2.6.
Chris B.
10
Ini mungkin bisa dikatakan, tetapi dengan python v2.6 +, Anda tidak perlu lagi mengimpor dari masa depan . dengan sekarang menjadi kata kunci kelas satu.
fitzgeraldsteele
25
Dalam 2,7 Anda dapat memiliki beberapa withs:) with open('filea') as filea and open('fileb') as fileb: ...
Austin Richardson
5
@Austin saya tidak bisa mendapatkan sintaks untuk bekerja pada 2.7. namun ini berhasil: with open('filea') as filea, open('fileb') as fileb: ...
wim
168

Kamus memiliki metode get ()

Kamus memiliki metode 'get ()'. Jika Anda melakukan d ['kunci'] dan kunci tidak ada di sana, Anda akan mendapatkan pengecualian. Jika Anda melakukannya d.get ('kunci'), Anda mendapatkan kembali Tidak ada jika 'kunci' tidak ada. Anda dapat menambahkan argumen kedua untuk mendapatkan item itu kembali sebagai ganti None, mis .: d.get ('key', 0).

Ini bagus untuk hal-hal seperti menambahkan angka:

sum[value] = sum.get(value, 0) + 1

Rory
sumber
39
juga, periksa metode setdefault.
Daren Thomas
27
juga, checkout kelas collections.defaultdict.
jfs
8
Jika Anda menggunakan Python 2.7 atau lebih baru, atau 3.1 atau lebih baru, periksa kelas Counter di modul koleksi. docs.python.org/library/collections.html#collections.Counter
Elias Zamaria
Ya ampun, selama ini yang kulakukan get(key, None). Tidak punya ide yang Nonedisediakan secara default.
Jordan Reiter
152

Penjelas

Mereka adalah keajaiban di balik sejumlah fitur inti Python.

Ketika Anda menggunakan akses bertitik untuk mencari anggota (misalnya, xy), Python pertama mencari anggota dalam kamus contoh. Jika tidak ditemukan, akan dicari di kamus kelas. Jika menemukannya di kamus kelas, dan objek mengimplementasikan protokol deskriptor, alih-alih mengembalikannya, Python menjalankannya. Sebuah descriptor adalah setiap kelas yang mengimplementasikan __get__, __set__atau __delete__metode.

Inilah cara Anda akan menerapkan versi properti Anda (hanya baca) menggunakan deskriptor:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

dan Anda akan menggunakannya seperti properti bawaan ():

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

Penjelas digunakan dalam Python untuk mengimplementasikan properti, metode terikat, metode statis, metode kelas, dan slot, di antara hal-hal lainnya. Memahami mereka membuatnya mudah untuk melihat mengapa banyak hal yang sebelumnya tampak seperti 'quirks' Python adalah cara mereka.

Raymond Hettinger memiliki tutorial yang sangat baik yang melakukan pekerjaan yang jauh lebih baik dalam menggambarkan mereka daripada saya.

Nick Johnson
sumber
Ini duplikat dekorator, bukan !? ( stackoverflow.com/questions/101268/… )
gecco
2
tidak, dekorator dan deskriptor adalah hal yang sangat berbeda, meskipun dalam kode contoh, saya membuat dekorator deskriptor. :)
Nick Johnson
1
Cara lain untuk melakukan ini adalah dengan lambda:foo = property(lambda self: self.__foo)
Pete Peterson
1
@PetePeterson Ya, tapi propertyitu sendiri diimplementasikan dengan deskriptor, yang merupakan titik posting saya.
Nick Johnson
142

Tugas Bersyarat

x = 3 if (y == 1) else 2

Itu tidak persis seperti apa terdengar: "tetapkan 3 ke x jika y adalah 1, jika tidak tetapkan 2 ke x". Perhatikan bahwa parens tidak diperlukan, tetapi saya suka agar mudah dibaca. Anda juga dapat mengaitkannya jika memiliki sesuatu yang lebih rumit:

x = 3 if (y == 1) else 2 if (y == -1) else 1

Meskipun pada titik tertentu, itu agak terlalu jauh.

Perhatikan bahwa Anda dapat menggunakan if ... else dalam ekspresi apa pun. Sebagai contoh:

(func1 if y == 1 else func2)(arg1, arg2) 

Di sini func1 akan dipanggil jika y adalah 1 dan func2, jika tidak. Dalam kedua kasus fungsi yang sesuai akan dipanggil dengan argumen arg1 dan arg2.

Secara analog, yang berikut ini juga valid:

x = (class1 if y == 1 else class2)(arg1, arg2)

dimana class1 dan class2 adalah dua kelas.

tghw
sumber
29
Tugas bukanlah bagian khusus. Anda dapat dengan mudah melakukan sesuatu seperti: mengembalikan 3 jika (y == 1) yang lain 2.
Brian
25
Cara alternatif itu adalah pertama kalinya saya melihat Python yang dikaburkan.
Craig McQueen
3
Kylebrooks: Tidak dalam kasus itu, operator boolean mengalami hubungan pendek. Ini hanya akan mengevaluasi 2 jika bool (3) == Salah.
RoadieRich
15
pengkodean gaya mundur ini membingungkan saya. sesuatu seperti x = ((y == 1) ? 3 : 2)lebih masuk akal bagi saya
mpen
13
Saya merasakan kebalikan dari @Mark, operator ternary C-style selalu membingungkan saya, apakah sisi kanan atau tengah apa yang dievaluasi pada kondisi yang salah? Saya lebih suka sintaksis ternary Python.
Jeffrey Harris
141

Doctest : dokumentasi dan pengujian unit pada saat bersamaan.

Contoh diekstrak dari dokumentasi Python:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()
Pierre-Jean Coudert
sumber
6
Doctests memang keren, tapi saya benar-benar tidak suka semua cruft Anda harus mengetik untuk menguji bahwa sesuatu harus menimbulkan pengecualian
TM.
60
Dokumen terlalu dibesar-besarkan dan mencemari dokumentasi. Seberapa sering Anda menguji fungsi mandiri tanpa setUp ()?
nerd dibayar
2
siapa bilang Anda tidak bisa memiliki setup di doctest? menulis fungsi yang menghasilkan konteks dan kembali locals()kemudian di Anda doctest lakukan locals().update(setUp())= D
Jiaaro
12
Jika fungsi mandiri memerlukan setUp, kemungkinan besar itu harus dipisahkan dari beberapa hal yang tidak terkait atau dimasukkan ke dalam kelas. Namespace doctest kelas kemudian dapat digunakan kembali dalam metode dokumentasi kelas, jadi agak seperti setUp, hanya KERING dan dapat dibaca.
Andy Mikhaylenko
4
"Seberapa sering Anda menguji fungsi mandiri" - banyak. Saya menemukan dokumen sering muncul secara alami dari proses desain ketika saya memutuskan pada fasad.
Gregg Lind
138

Pemformatan yang diberi nama

% -formatting mengambil kamus (juga berlaku validasi% i /% s dll.)

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

Dan karena penduduk lokal () juga merupakan kamus, Anda dapat dengan mudah menyampaikannya sebagai dict dan memiliki% -substitions dari variabel lokal Anda. Saya pikir ini disukai, tetapi menyederhanakan hal-hal ..

Pemformatan Gaya Baru

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
Pasi Savolainen
sumber
60
Akan dihapus dan akhirnya diganti dengan metode string ().
Constantin
3
Pemformatan yang dinamai sangat berguna untuk penerjemah karena mereka cenderung hanya melihat string format tanpa nama variabel untuk konteks
pixelbeat
2
Tampaknya berfungsi di python 3.0.1 (diperlukan untuk menambahkan tanda kurung di sekitar panggilan cetak).
Pasi Savolainen
9
sebuah hash , ya? Saya melihat dari mana Anda berasal.
shylent
11
Pemformatan% s tidak akan dihapus. str.format () tentu saja lebih pythonic, namun sebenarnya 10x lebih lambat untuk penggantian string sederhana. Keyakinan saya adalah pemformatan% s masih merupakan praktik terbaik.
Kenneth Reitz
132

Untuk menambahkan lebih banyak modul python (terutama yang pihak ke-3), kebanyakan orang tampaknya menggunakan variabel lingkungan PYTHONPATH atau mereka menambahkan symlink atau direktori di direktori paket-situs mereka. Cara lain, adalah dengan menggunakan file * .pth. Berikut penjelasan resmi python doc:

"Cara paling mudah [untuk memodifikasi jalur pencarian python] adalah dengan menambahkan file konfigurasi path ke direktori yang sudah ada di path Python, biasanya ke ... / situs-paket / direktori. File konfigurasi path memiliki ekstensi .pth , dan setiap baris harus berisi jalur tunggal yang akan ditambahkan ke sys.path. (Karena jalur baru ditambahkan ke sys.path, modul di direktori yang ditambahkan tidak akan menimpa modul standar. Ini berarti Anda tidak dapat menggunakan mekanisme ini untuk menginstal versi tetap dari modul standar.) "

dgrant
sumber
1
Saya tidak pernah membuat koneksi antara file .pth di direktori paket situs dari setuptools dan ide ini. luar biasa.
dave paola
122

Klausa pengecualian lain :

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

Penggunaan klausa lain lebih baik daripada menambahkan kode tambahan ke klausa coba karena menghindari secara tidak sengaja menangkap pengecualian yang tidak dimunculkan oleh kode yang dilindungi oleh percobaan ... kecuali pernyataan.

Lihat http://docs.python.org/tut/node10.html

Konstantin
sumber
8
+1 ini luar biasa. Jika blok coba dijalankan tanpa memasukkan blok pengecualian, maka blok yang lain dimasukkan. Dan tentu saja, blok akhirnya dieksekusi
inspectorG4dget
Saya akhirnya mengerti mengapa 'yang lain' ada di sana! Terima kasih.
taynaron
Akan lebih masuk akal untuk menggunakan terus, tapi saya rasa itu sudah diambil;)
Paweł Prażak
Perhatikan bahwa pada versi Python2 lama Anda tidak dapat memiliki keduanya: dan akhirnya: klausa untuk percobaan yang sama: blok
Kevin Horn
1
@ Paweł Prażak, seperti yang disebutkan oleh Kevin Horn, sintaks ini diperkenalkan setelah rilis awal Python dan menambahkan kata kunci cadangan baru ke bahasa yang ada selalu bermasalah. Itu sebabnya kata kunci yang ada biasanya digunakan kembali (cf "auto" dalam standar C ++ baru-baru ini).
Constantin
114

Memunculkan kembali pengecualian :

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

Pernyataan 'naikkan' tanpa argumen di dalam penangan kesalahan memberitahu Python untuk menaikkan kembali pengecualian dengan traceback asli yang utuh , memungkinkan Anda untuk mengatakan "oh, maaf, maaf, saya tidak bermaksud menangkap itu, maaf, maaf. "

Jika Anda ingin mencetak, menyimpan, atau mengutak-atik traceback asli, Anda bisa mendapatkannya dengan sys.exc_info (), dan mencetaknya seperti yang dilakukan Python dilakukan dengan modul 'traceback'.

Thomas Wouters
sumber
Maaf, tetapi ini adalah fitur yang terkenal dan umum dari hampir semua bahasa.
Lucas S.
6
Perhatikan teks yang dicetak miring. Beberapa orang akan melakukannya raise e, yang tidak mempertahankan traceback aslinya.
habnabit
12
Mungkin lebih ajaib, exc_info = sys.exc_info(); raise exc_info[0], exc_info[1], exc_info[2]setara dengan ini, tetapi Anda dapat mengubah nilai-nilai itu di sekitar (misalnya, mengubah jenis pengecualian atau pesan)
ianb
3
@Lucas S. Yah, saya tidak tahu, dan saya senang itu ditulis di sini.
e-satis
saya mungkin menunjukkan masa muda saya di sini, tetapi saya selalu menggunakan sintaks python 3 di python 2.7 tanpa masalah
wim
106

Pesan utama :)

import this
# btw look at this module's source :)

Di-cyphered :

Zen Python, oleh Tim Peters

Cantik lebih baik dari yang jelek.
Eksplisit lebih baik daripada implisit.
Sederhana lebih baik daripada kompleks.
Kompleks lebih baik daripada rumit.
Flat lebih baik daripada bersarang.
Jarang lebih baik daripada padat.
Jumlah keterbacaan diperhitungkan.
Kasus khusus tidak cukup istimewa untuk melanggar aturan.
Meskipun kepraktisan mengalahkan kemurnian.
Kesalahan tidak boleh terjadi secara diam-diam.
Kecuali secara eksplisit dibungkam.
Dalam menghadapi ambiguitas, tolak godaan untuk menebak. Harus ada satu - dan lebih disukai hanya satu - cara yang jelas untuk melakukannya.
Meskipun demikian mungkin tidak jelas pada awalnya kecuali Anda orang Belanda.
Sekarang lebih baik daripada tidak sama sekali.
Meskipun tidak pernah sering lebih baik daripadatepat sekarang.
Jika implementasinya sulit dijelaskan, itu ide yang buruk.
Jika implementasinya mudah dijelaskan, mungkin itu ide yang bagus.
Namespaces adalah salah satu ide bagus - mari kita lakukan lebih banyak lagi!

Tandai
sumber
1
Adakah yang tahu mengapa sumber itu di-cypher dengan cara itu? Apakah hanya untuk bersenang-senang, atau ada alasan lain?
MiniQuark
42
cara sumber ditulis bertentangan dengan zen!
Hasen
2
Saya telah memperbarui /usr/lib/python2.6/this.py saya mengganti kode lama dengan ini print s.translate("".join(chr(64<i<91 and 65+(i-52)%26 or 96<i<123 and 97+(i-84)%26 or i) for i in range(256)))dan terlihat jauh lebih baik sekarang !! :-D
fortran
2
@MiniQuark: pelajaran sejarah cepat: wefearchange.org/2010/06/import-this-and-zen-of-python.html
105

Penyelesaian Tab Interpreter Interaktif

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

Anda juga harus menetapkan variabel lingkungan PYTHONSTARTUP.

mjard
sumber
2
Ini adalah fitur yang sangat berguna. Begitu banyak sehingga saya memiliki skrip sederhana untuk mengaktifkannya (ditambah beberapa penyempurnaan introspeksi lainnya): pixelbeat.org/scripts/inpy
pixelbeat
43
IPython memberi Anda ini dan banyak lagi barang
akaihola
Ini akan lebih berguna di pdb prompt daripada prompt python biasa (seperti IPython melayani tujuan itu pula). Namun, ini sepertinya tidak berfungsi pada prompt pdb, mungkin karena pdb mengikat sendiri untuk tab (yang kurang bermanfaat). Saya mencoba memanggil parse_and_bind () di prompt pdb, tetapi masih tidak berhasil. Alternatif mendapatkan pdb prompt dengan IPython lebih banyak bekerja jadi saya cenderung tidak menggunakannya.
haridsv
2
@ haridsv - easy_install ipdb- maka Anda dapat menggunakanimport ipdb; ipdb.set_trace()
Doug Harris
1
Di osx [dan saya bayangkan sistem lain yang menggunakan libedit] yang harus Anda lakukanreadline.parse_and_bind ("bind ^I rl_complete")
Foo Bah
91

Pemahaman daftar bersarang dan ekspresi generator:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

Ini dapat menggantikan potongan besar kode nested-loop.

Rafał Dowgird
sumber
"for j in range (i)" - apakah ini salah ketik? Biasanya Anda ingin rentang tetap untuk i dan j. Jika Anda mengakses array 2d, Anda akan kehilangan setengah elemen Anda.
Peter Gibson
Saya tidak mengakses array apa pun dalam contoh ini. Satu-satunya tujuan kode ini adalah untuk menunjukkan bahwa ekspresi dari rentang dalam dapat mengakses ekspresi dari luar. Produk sampingan adalah daftar pasangan (x, y) sehingga 4> x> y> 0.
Rafał Dowgird
2
agak seperti integrasi ganda dalam kalkulus, atau penjumlahan ganda.
Yoo
22
Poin kunci untuk diingat di sini (yang membutuhkan waktu lama untuk saya sadari) adalah bahwa urutan forpernyataan harus ditulis dalam urutan yang Anda harapkan ditulis dalam standar untuk-loop, dari luar ke dalam.
sykora
2
Untuk menambahkan komentar sykora: bayangkan Anda mulai dengan setumpuk fors dan ifs dengan yield xdi dalamnya. Untuk mengonversinya menjadi ekspresi generator, pindahkan xdulu, hapus semua titik dua (dan yield), dan mengelilingi semuanya dalam tanda kurung. Untuk membuat daftar pemahaman sebagai gantinya, ganti parens luar dengan tanda kurung.
Ken Arnold
91

Overloading operator untuk setbuiltin:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

Lebih detail dari referensi pustaka standar: Set Type

Kiv
sumber
Dalam tutorial ini, sebagian docs.python.org/tutorial/datastructures.html#sets
XTL