Kiat untuk bermain golf dengan Python


248

Apa tips umum yang Anda miliki untuk bermain golf di Python? Saya mencari ide yang dapat diterapkan pada masalah kode-golf dan yang juga setidaknya agak spesifik untuk Python (mis. "Hapus komentar" bukan jawaban).

Silakan kirim satu tip per jawaban.


27
Oh, saya bisa melihat serangkaian pertanyaan seperti ini datang untuk setiap bahasa ...
R. Martinho Fernandes

4
@Martinho saya setuju. Baru saja memulai C ++ yang setara . Saya tidak berpikir itu hal yang buruk, selama kita tidak melihat jawaban yang sama diposting ulang di banyak jenis pertanyaan ini.
marcog

50
Saya suka pertanyaannya tetapi saya harus terus mengatakan pada diri sendiri "Ini HANYA untuk bersenang-senang BUKAN untuk kode produksi"
Greg Guida

2
Bukankah seharusnya pertanyaan ini menjadi posting wiki komunitas?
dorukayhan

3
@dorukayhan Tidak; itu pertanyaan kiat kode golf yang valid , meminta kiat tentang pemendekan kode python untuk keperluan CG'ing. Pertanyaan-pertanyaan seperti itu benar-benar valid untuk situs, dan tidak ada dari tag ini yang secara eksplisit mengatakan bahwa pertanyaan itu harus CW, tidak seperti SO, yang mengharuskan tantangan CG menjadi CW. Juga, menulis jawaban yang baik, dan menemukan kiat-kiat seperti itu selalu layak mendapatkan sesuatu, yang diambil jika pertanyaannya adalah komunitas wiki (perwakilan).
Erik the Outgolfer

Jawaban:


152

Gunakan a=b=c=0sebagai ganti a,b,c=0,0,0.

Gunakan a,b,c='123'sebagai ganti a,b,c='1','2','3'.


2
itu tip yang bagus secara umum :)

28
Perhatikan bahwa ini tidak akan bekerja untuk mendefinisikan objek yang bisa diubah yang akan Anda modifikasi di tempat. a = b = [1] sebenarnya berbeda dari a = [1]; b = [1]
isaacg

6
Yang lucu tentang tip pertama adalah bahwa ia bekerja di Jawa juga.
Justin

1
@ Justin Ya, tetapi hanya dengan tipe primitif
HyperNeutrino

11
Tapi JANGAN PERNAH menggunakan a = b = c = [] atau instanciasi objek apa pun karena semua variabel akan menunjuk ke instance yang sama. Mungkin itu bukan yang Anda inginkan.
PhE

146

Persyaratan bisa panjang. Dalam beberapa kasus, Anda dapat mengganti kondisional sederhana dengan (a,b)[condition]. Jika conditionbenar, maka bdikembalikan.

Membandingkan

if a<b:return a
else:return b

Untuk ini

return(b,a)[a<b]

37
Ini tidak persis sama. Yang pertama hanya mengevaluasi ekspresi yang dikembalikan sementara yang kedua selalu mengevaluasi keduanya. Yang ini melakukan hubungan arus pendek: a if a<b else bdana<b and a or b
marinus

3
(lambda(): b, lambda(): a)[a < b]()buat hubungan arus pendek Anda sendiri dengan lambdas
Ming-Tang

3
@marinus, mereka tidak sama: hanya mempertimbangkan P and A or Buntuk setiap A yang memberi bool(A)=False. Tetapi (P and [A] or [B])[0]akan melakukan pekerjaan. Lihat diveintopython.net/power_of_introspection/and_or.html untuk referensi.
kgadek

6
Lambdas jauh lebih lama daripada ekspresi kondisional.
user2357112

18
@ user2357112 Tapi mereka membuat Anda terlihat jauh lebih keren saat Anda menggunakannya. :]
Chase Ries

117

Suatu hal hebat yang pernah saya lakukan adalah:

if 3 > a > 1 < b < 5: foo()

dari pada:

if a > 1 and b > 1 and 3 > a and 5 > b: foo()

Operator perbandingan Python mengguncang.


Menggunakan semuanya sebanding dengan Python 2, Anda juga dapat menghindari andoperator dengan cara ini. Sebagai contoh, jika a, b, cdan dadalah bilangan bulat,

if a<b and c>d:foo()

dapat disingkat oleh satu karakter ke:

if a<b<[]>c>d:foo()

Ini menggunakan bahwa setiap daftar lebih besar dari bilangan bulat apa pun.

Jika cdan dadalah daftar, ini menjadi lebih baik:

if a<b<c>d:foo()

22
Tentu saja jika ini benar-benar golf itu akan3>a>1<b<5
Rafe Kettler

4
Cinta simetri. Mengingatkan saya pada trik golf Perl lama untuk menemukan min $ a dan $ b: [$a => $b]->[$b <= $a]:)
Simon Whitaker

Perhatikan bahwa contoh kedua (tanpa daftar) juga dapat dilakukan denganif(a<b)+(c>d):foo()
WorldSEnder

6
Tanda + harus a *. An orakan menjadi+
WorldSEnder

1
foo()if 3>a>1<b<5
Erik the Outgolfer

103

Jika Anda menggunakan fungsi bawaan berulang kali, mungkin akan lebih hemat tempat untuk memberinya nama baru, jika menggunakan argumen yang berbeda:

r=range
for x in r(10):
 for y in r(100):print x,y

6
Namun sebenarnya tidak menyimpan byte.
user2357112

4
r = range dan dua r lainnya adalah 9 karakter; menggunakan rentang dua kali adalah 10 karakter. Bukan penghematan besar dalam contoh ini, tetapi yang diperlukan hanyalah satu lagi penggunaan rentang untuk melihat penghematan yang signifikan.
Frank

13
@ Frank Baris baru tambahan adalah karakter lain.
L3viathan

2
Memang dua pengulangan terlalu sedikit untuk disimpan pada nama fungsi panjang lima. Anda membutuhkan: panjang 2: 6 repetisi, panjang 3: 4 repetisi, panjang 4 atau 5: 3 repetisi, panjang> = 6: 2 repetisi. AKA (panjang-1) * (reps-1)> 4.
Ørjan Johansen

Catatan ini berlaku untuk semua bahasa dengan fungsi kelas satu.
bfontaine

94

Terkadang kode Python Anda mengharuskan Anda memiliki 2 tingkat lekukan. Yang jelas harus dilakukan adalah menggunakan satu dan dua ruang untuk setiap level indentasi.

Namun, Python 2 menganggap tab dan karakter spasi sebagai level indentasi yang berbeda.

Ini berarti level indentasi pertama dapat berupa satu spasi dan yang kedua dapat menjadi satu karakter tab.

Sebagai contoh:

if 1:
 if 1:
\tpass

Di mana \tkarakter tab.


1
Keren, saya tidak pernah memikirkan yang ini!
Jules Olléon

97
Ini gagal di python3: Anda tidak bisa lagi mencampur ruang dan tab (hal yang buruk untuk codegolf, tetapi hal yang baik dalam semua kasus lainnya).
Bakuriu

1
Dalam python 3.4 ini sepertinya berfungsi dengan baik.
trichoplax

3
@trichoplax , Dalam python 3.4.3 saya dapatkanTabError: inconsistent use of tabs and spaces in indentation.
ceilingcat

Sebagai referensi, sebuah tab bernilai 8 spasi.
Erik the Outgolfer

87

Gunakan substitusi string dan execuntuk berurusan dengan kata kunci panjang seperti lambdayang sering diulang dalam kode Anda.

a=lambda b:lambda c:lambda d:lambda e:lambda f:0   # 48 bytes  (plain)
exec"a=`b:`c:`d:`e:`f:0".replace('`','lambda ')    # 47 bytes  (replace)
exec"a=%sb:%sc:%sd:%se:%sf:0"%(('lambda ',)*5)     # 46 bytes  (%)

String target sangat sering 'lambda ', yaitu 7 byte. Misalkan cuplikan kode Anda berisi nkejadian 'lambda ', dan spanjang byte. Kemudian:

  • The plainpilihan adalah sbyte panjang.
  • The replacepilihan adalah s - 6n + 29byte panjang.
  • The %pilihan adalah s - 5n + 22 + len(str(n))byte panjang.

Dari sebidang byte yang disimpanplain untuk ketiga opsi ini, kita dapat melihat bahwa:

  • Untuk n <5 lambdas, Anda lebih baik tidak melakukan sesuatu yang mewah sama sekali
  • Untuk n = 5 , menulis exec"..."%(('lambda ',)*5)menyimpan 2 byte, dan merupakan pilihan terbaik Anda.
  • Untuk n> 5 , menulis exec"...".replace('`','lambda ')adalah pilihan terbaik Anda.

Untuk kasus lain, Anda dapat mengindeks tabel di bawah ini:

          1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 (occurences)
       +---------------------------------------------------------
     3 |  -  -  -  -  -  -  -  -  -  -  -  -  -  -  r  r  r  r  r  
     4 |  -  -  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  
     5 |  -  -  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  
     6 |  -  -  -  -  -  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     7 |  -  -  -  -  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     8 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
     9 |  -  -  -  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    10 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    11 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
    12 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r = replace
    13 |  -  -  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   % = string %
    14 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r   - = do nothing
    15 |  -  %  %  %  %  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
  (length)

Misalnya, jika string lambda x,y:(panjang 11) muncul 3 kali dalam kode Anda, Anda lebih baik menulis exec"..."%(('lambda x,y:',)*3).


4
ini harus mendapatkan lebih banyak suara, ini tip yang sangat berguna.
bigblind

7
itu sangat jarang bahwa ini bekerja. biaya replacesangat besar.
stan

4
Tetapi ketika itu berhasil, itu sangat membantu.
undergroundmonorail

Menarik, bahkan tidak pernah memikirkan hal ini!
Claudiu

Saya menambahkan operator baru untuk lambda dalam bahasa saya berdasarkan dari python: =>hanya string = lambda . Misalnya, f=>:0akan f = lambda: 0.
NoOneIsHere

78

Gunakan pengirisan panjang untuk memilih satu string dari banyak string

>>> for x in 0,1,2:print"fbboaaorz"[x::3]
... 
foo
bar
baz

vs.

>>> for x in 0,1,2:print["foo","bar","baz"][x]
... 
foo
bar
baz

Dalam case dua-string Boolean ini, kita juga bisa menulis

b*"string"or"other_string"

untuk

["other_string","string"][b]

Tidak seperti interleaving, ini bekerja untuk string dengan panjang berapa pun, tetapi dapat memiliki masalah prioritas operator jika bbukan ekspresi.


Perhatikan bahwa contoh pertama persis sama panjangnya denganfor x in ("foo","bar","baz"): print x
Mateen Ulhaq

1
@MateenUlhaq, Itu hanya sebuah contoh bagaimana nilai-nilai berbeda dari xyang diberikan. Bagian golf adalah "fbboaaorz"[x::3]vs ["foo","bar","baz"][x]Bagaimana xnilai didapat akan menjadi bagian lain dari solusi golf Anda.
gnibbler

72

Gunakan `n`untuk mengonversi bilangan bulat ke string alih-alih menggunakan str(n):

>>> n=123
>>> `n`
'123'

38
Bagus, tetapi tidak berfungsi dengan Python3.
Alexandru

2
Perhatian: benar-benar berfungsi untuk bilangan bulat, tetapi tidak untuk string, misalnya.
Nakilon

41
btw. `` kependekan dari repr
Alexandru

9
Integer yang lebih kecil dari -2 ** 31 atau lebih besar dari 2 ** 31-1 (Longs) mendapat 'L' yang ditempel di akhir.
hallvabo

6
Ini juga dapat digunakan untuk mencetak mengapung dengan presisi penuh
gnibbler

69

Menyimpan tabel pencarian sebagai angka ajaib

Katakanlah Anda ingin meng-hardcode tabel pencarian Boolean, seperti yang mana dari dua belas angka pertama bahasa Inggris yang mengandung n.

0: False
1: True
2: False
3: False
4: False
5: False
6: False
7: True
8: False
9: True
10:True
11:True
12:False

Kemudian, Anda bisa mengimplementasikan tabel pencarian ini dengan ringkas sebagai:

3714>>i&1

dengan hasil 0atau 1sama Falsedengan True.

Idenya adalah bahwa angka ajaib menyimpan tabel sebagai bitstring bin(3714)= 0b111010000010, dengan ndigit -th (dari ujung) yang sesuai dengan nentri tabel th. Kami mengakses nentri th dengan bithifting nruang angka ke kanan dan mengambil digit terakhir &1.

Metode penyimpanan ini sangat efisien. Bandingkan dengan alternatifnya

n in[1,7,9,10,11]
'0111010000010'[n]>'0'

Anda dapat membuat tabel pencarian Anda menyimpan entri multibit yang dapat diekstraksi seperti

 340954054>>4*n&15

untuk mengekstrak blok empat-bit yang relevan.


Bisakah kita memiliki contoh hasil untuk blok empat-bit? Apakah Anda menggunakan aturan untuk blok n-bit?
JeromeJ

8
Hex kadang-kadang bahkan lebih kecil.
Joonazan

4
Ini berguna untuk banyak bahasa.
Cyoce

1
@Joonazan Hex lebih kecil untuk nomor lebih dari 999 999 .
Mateen Ulhaq

60

Perkecil dua loop numerik menjadi satu

Katakanlah Anda melakukan iterasi pada sel-sel m*ngrid Alih-alih dua forloop bersarang , satu untuk baris dan satu kolom, biasanya lebih pendek untuk menggunakan satu loop untuk beralih di atas m*nsel - sel grid. Anda bisa mengekstrak baris dan kolom sel di dalam loop.

Kode asli:

for i in range(m):
 for j in range(n):
  do_stuff(i,j)

Kode golf:

for k in range(m*n):
  do_stuff(k/n,k%n)

Akibatnya, Anda mengulangi produk Cartesian dari dua rentang, menyandikan pasangan (i,j)sebagai x=i*n+j. Anda telah menyimpan rangepanggilan mahal dan tingkat lekukan di dalam loop. Urutan iterasi tidak berubah.

Gunakan //daripada /di Python 3. Jika Anda merujuk idan jberkali-kali, mungkin lebih cepat untuk menetapkan nilainya i=k/n, j=k%ndi dalam loop.


5
Ini luar biasa. Saya tidak pernah menyadari ini mungkin!
theonlygusti

Saya melihat ini di tips untuk JavaScript. Ini adalah trik yang cukup berguna di sebagian besar bahasa.
Cyoce

7
Sebagai referensi, untuk memperpanjang ini menjadi 3 loop:for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o)
mbomb007

3
Untuk nloop: repl.it/EHwa
mbomb007

Dalam beberapa kasus, itertools.productbisa jauh lebih ringkas daripada loop bersarang, terutama ketika menghasilkan produk cartesian. a1, a2, b1, b2adalah contoh dari produk kartesius 'ab'dan'12'
Aaron3468

54

Kecuali jika token berikut dimulai dengan eatau E. Anda dapat menghapus ruang mengikuti nomor.

Misalnya:

if i==4 and j==4:
    pass

Menjadi:

if i==4and j==4:
    pass

Menggunakan ini dalam pernyataan satu baris yang rumit dapat menyimpan beberapa karakter.

EDIT: seperti yang ditunjukkan @marcog, 4or aakan berfungsi, tetapi tidak a or4karena ini akan membingungkan dengan nama variabel.


37
if(i,j)==(4,4):bahkan lebih pendek dan dalam kasus khusus iniif i==j==4:
gnibbler

3
Terkait: 4or abekerja, tetapi tidaka or4
marcog

17
0orjuga tidak berfungsi ( 0omerupakan awalan untuk angka oktal).
Nabb

5
@ Nabb Bukan berarti itu penting, karena 0 or xselalu akan kembali x. Mungkin juga memotong 0 or.
Aprıʇǝɥʇuʎ

5
0orbaik-baik saja sebagai bagian dari angka yang lebih lama. 10 or xsetara dengan 10or x.
trichoplax

54

Untuk integer n, Anda bisa menulis

  • n+1 sebagai -~n
  • n-1 sebagai ~-n

karena bit flip ~xsama dengan -1-x. Ini menggunakan jumlah karakter yang sama, tetapi secara tidak langsung dapat memotong spasi atau paren sebagai prioritas operator.

Membandingkan:

while n-1:  #Same as while n!=1 
while~-n:

c/(n-1)
c/~-n

or f(n)+1
or-~f(n) 

(n-1)/10+(n-1)%10
~-n/10+~-n%10

Operator ~dan unary -yang diutamakan lebih tinggi dari *, /, %, tidak seperti biner +.


11
Sebuah variasi pada trik ini aku berlari ke hari ini: -~-xmenghemat satu byte vs (1-x).
Lynn

4
Aplikasi lain yang bermanfaat adalah yang a+b+1dapat ditulis secara lebih ringkas a-~b.
Strigoides

Dan n-i-1itu adil n+~i.
ruohola

51

Cara yang bagus untuk mengonversi iterable ke daftar di Python 3 :

bayangkan Anda memiliki beberapa iterable, like

i = (1,2,3,4)
i = range(4)
i = (x**2 for x in range(5))

Tetapi Anda perlu daftar:

x=list(i)  #the default way
*x,=i      #using starred assignment -> 4 char fewer

Sangat berguna untuk membuat daftar karakter dari string

s=['a','b','c','d','e']
s=list('abcde')
*s,='abcde'

1
mengetik *s,='abcde'dan kemudian scrash python3 interaktif saya dengan segfault :(
daniero

@daniero Wow. Hanya di konsol interaktif? Kedengarannya sangat aneh. Cobalah di konsol bersih atau laporkan bug
JBernardo 6-15

1
Python 3.5 saya berfungsi dengan baik.
NoOneIsHere

untuk i = (x ** 2 untuk x dalam kisaran (5)) Saya mendapatkan kode ini dikembalikan <generator objek <genexpr> di 0x03321690>
george

7
Dan jika Anda melakukan ini dalam ekspresi, Anda bisa melakukannya [*'abcde'].
Buah Esolanging

46

Alih-alih range(x), Anda dapat menggunakan *operator pada daftar apa pun, jika Anda tidak benar-benar perlu menggunakan nilai i:

for i in[1]*8:pass

sebagai lawan

for i in range(8):pass

Jika Anda perlu melakukan ini lebih dari dua kali, Anda bisa menetapkan setiap iterable ke variabel, dan gandakan variabel itu dengan rentang yang Anda inginkan:

r=1,
for i in r*8:pass
for i in r*1000:pass

Catatan : ini seringkali lebih lama daripada exec"pass;"*8, jadi trik ini seharusnya hanya digunakan ketika itu bukan pilihan.


@proudhaskeller Saya pikir inti dari garis yang Anda hapus adalah bahwa "Selain penghematan karakter yang jelas Anda dapatkan karena [1]*8lebih pendek daripada range(8), Anda juga bisa menghemat ruang karena for i in[...legal sementara for i in range...tidak".
undergroundmonorail

oh benar, aku tidak mengerti itu. diperbaiki sekarang
haskeller bangga

7
exec"pass;"*8secara signifikan lebih pendek.
DJMcMayhem

1
Jika r=1, r*8adalah 8, dan Anda tidak dapat mengulangi melalui nomor. Saya kira Anda maksudr=[1]
Artemis Fowl

1
@ ArtemisFowl, tidak apa-apa, koma setelah 1 menciptakan tuple yang dapat diubah.
sasha

43

Anda dapat menggunakan wajah smiley alien yang lama untuk membalik urutan:

[1, 2, 3, 4][::-1] # => [4, 3, 2, 1]

38

Pembongkaran yang diperpanjang iterable ("Penugasan berbintang", hanya Python 3)

Cara terbaik untuk menjelaskan ini adalah melalui contoh:

>>> a,*b,c=range(5)
>>> a
0
>>> b
[1, 2, 3]
>>> c
4

Kami telah melihat manfaatnya - mengubah iterable menjadi daftar dengan Python 3 :

a=list(range(10))
*a,=range(10)

Berikut adalah beberapa kegunaan lagi.

Mendapatkan elemen terakhir dari daftar

a=L[-1]
*_,a=L

Dalam beberapa situasi, ini juga dapat digunakan untuk mendapatkan elemen pertama untuk menghemat parens:

a=(L+[1])[0]
a,*_=L+[1]

Menetapkan daftar kosong dan variabel lainnya

a=1;b=2;c=[]
a,b,*c=1,2

Menghapus elemen pertama atau terakhir dari daftar yang tidak kosong

_,*L=L
*L,_=L

Ini lebih pendek dari alternatif L=L[1:]dan L.pop(). Hasilnya juga dapat disimpan ke daftar yang berbeda.

Kiat milik @grc


Wow! Saya telah menulis a=1;L=[]berkali-kali. Sungguh menakjubkan bahwa Anda dapat menyimpan karakter pada sesuatu yang sangat mudah seperti ini.
xnor

@ xnor Yang itu berkat grc. Dengan hanya satu elemen lain itu tidak sebagus ( a,*L=1,), tetapi masih menyimpan satu char :)
Sp3000

jangan lupa Anda juga bisa mendapatkan elemen pertama dan terakhir dari daftar dengana,*_,b=L
Cyoce

36

atur literal dalam Python2.7

Anda dapat menulis set seperti ini S={1,2,3}Ini juga berarti Anda dapat memeriksa keanggotaan menggunakan {e}&Salih-alih e in Syang menyimpan satu karakter.


4
Dan ini juga menyimpan karakter dalam ifs karena tidak ada spasi ( if{e}&S:)
Artyer

1
Perhatikan bahwa Anda dapat mengganti not indengan {e}-Sdengan trik yang
Hitam Owl Kai

35

Selama berabad-abad itu mengganggu saya bahwa saya tidak bisa memikirkan cara singkat untuk mendapatkan seluruh alfabet. Jika Anda menggunakan rangecukup yang R=rangelayak dimiliki dalam program Anda, maka

[chr(i+97)for i in R(26)]

lebih pendek dari yang naif

'abcdefghijklmnopqrstuvwxyz'

, tapi selain itu lebih panjang dengan satu karakter. Itu menghantui saya bahwa yang pandai yang membutuhkan pengetahuan tentang nilai-nilai ascii akhirnya menjadi lebih bertele-tele daripada hanya mengetik semua huruf.

Sampai saya melihat jawaban ini untuk My Daughter's Alphabet . Saya tidak bisa mengikuti riwayat sunting dengan cukup baik untuk mengetahui apakah jenius ini adalah karya OP atau apakah itu adalah saran dari seorang komentator, tetapi ini (saya percaya) adalah cara terpendek untuk membuat iterable dari 26 huruf dalam alfabet Romawi.

map(chr,range(97,123))

Jika huruf besar tidak penting, Anda dapat menghapus karakter lain dengan menggunakan huruf besar:

map(chr,range(65,91))

Saya menggunakan mapterlalu banyak, saya tidak tahu bagaimana ini tidak pernah terjadi pada saya.


4
Mungkin menggunakan ini dalam pengkodean aktual, saya merasa sangat bodoh ketika melakukan hardcoding pada hal-hal ini: ')
ToonAlfrink

37
Dalam pengkodean aktual, gunakan string.lowercase- itulah gunanya .
Kevin S

1
jika Anda membutuhkan kedua kasus, cara terpendek yang saya tahu adalah filter (str.isalpha, map (chr, range (256))). Hanya saja lebih pendek dari s = map (chr, range (256)); s + = map (str.lower, s)
quintopia

@quintopia: Mengapa 256, bukannya 122 ( ord('z'))? Selain panjangnya sama ... Selain itu, jika Anda membutuhkan alfanumerik, ganti str.isalphadengan versi @ quintopia dengan str.isalnum. (Tetapi jika Anda hanya membutuhkan satu kasing, seluruh string 36-karakter tidak lebih dari filter(str.isalnum,map(chr,range(90))).)
Tim Pederick

2
Jika Anda tidak adil dan menggunakan rentang sebagai R, versi saya lebih pendek daripada yang asli: '%c'*26%tuple(R(97,123))(hanya 24 karakter) jika Anda mengeja rangeitu asalkan alfabet - versi huruf besar lebih pendek
JBernardo

32

Meskipun python tidak memiliki pernyataan peralihan, Anda dapat meniru mereka dengan kamus. Misalnya, jika Anda menginginkan sakelar seperti ini:

switch (a):
    case 1:
        runThisCode()
        break
    case 2:
        runThisOtherCode()
        break
    case 3:
        runThisOtherOtherCode()
        break

Anda bisa menggunakan ifpernyataan, atau Anda bisa menggunakan ini:

exec{1:"runThisCode()",2:"runThisOtherCode()",3:"runThisOtherOtherCode()"}[a]

atau ini:

{1:runThisCode,2:runThisOtherCode,3:runThisOtherOtherCode}[a]()

yang lebih baik jika semua jalur kode berfungsi dengan parameter yang sama.

Untuk mendukung nilai default, lakukan ini:

exec{1:"runThisCode()"}.get(a,"defaultCode()")

(atau ini:)

­­{1:runThisCode}.get(a,defaultCode)()

Satu keuntungan lain dari hal ini adalah bahwa jika Anda memang memiliki kelebihan, Anda bisa menambahkannya setelah akhir kamus:

exec{'key1':'code','key2':'code'}[key]+';codeThatWillAlwaysExecute'

Dan jika Anda hanya ingin menggunakan sakelar untuk mengembalikan nilai:

def getValue(key):
    if key=='blah':return 1
    if key=='foo':return 2
    if key=='bar':return 3
    return 4

Anda bisa melakukan ini:

getValue=lambda key:{'blah':1,'foo':2,'bar',3}.get(key,4)

2
Ini adalah sesuatu yang saya akan pertimbangkan untuk menggunakannya di alam liar. Saya sangat merindukan pernyataan pergantian saya! +1
HalosGhost

1
Meskipun alih-alih menggunakan kamus dengan kunci bernomor pada contoh pertama, Anda sebaiknya menggunakan daftar
Cyoce

1
Jika Anda memiliki string sebagai kunci, gunakan dict(s1=v1,s2=v2,...,sn=vn)alih-alih {'s1':v1,'s2':v2,...,'sn':vn}menyimpan 2 * n-4 byte dan lebih baik jika n> = 3
Black Owl Kai

31

Ketika Anda memiliki dua nilai boolean, adan b, jika Anda ingin mengetahui apakah keduanya adan bitu benar, gunakan *sebagai ganti and:

if a and b: #7 chars

vs.

if a*b: #3 chars

jika salah satu nilai salah, itu akan mengevaluasi seperti 0dalam pernyataan itu, dan nilai integer hanya benar jika bukan nol.


9
Atau Anda bisa menggunakan &: a=b=False,a&b
ɐɔıʇǝɥʇuʎs

3
gunakan +untuk orjika Anda bisa menjamina != -b
undergroundmonorail

2
|berfungsi dalam semua situasi.
CalculatorFeline

1
*bukannya and/ &&menyimpan beberapa byte dalam banyak bahasa.
wastl

26

Mengeksploitasi representasi string Python 2

Python 2 memungkinkan Anda mengonversi objek xke representasi string `x`dengan biaya hanya 2 karakter. Gunakan ini untuk tugas-tugas yang lebih mudah dilakukan pada string objek daripada objek itu sendiri.

Gabung karakter

Diberikan daftar karakter l=['a','b','c'], seseorang dapat menghasilkan ''.join(l)sebagai `l`[2::5], yang menyimpan byte.

Alasannya adalah bahwa `l`ini "['a', 'b', 'c']"(dengan spasi), sehingga seseorang dapat mengekstrak huruf dengan daftar slice, mulai bahwa karakter nol-diindeks kedua a, dan mengambil setiap karakter kelima dari sana. Ini tidak berfungsi untuk bergabung dengan string multi-karakter atau karakter melarikan diri yang diwakili seperti '\n'.

Digit gabungan

Demikian pula, diberikan daftar non-kosong digit seperti l=[0,3,5], seseorang dapat menggabungkannya ke dalam string '035'sebagai `l`[1::3].

Ini menghemat melakukan sesuatu seperti map(str,l). Perhatikan bahwa mereka harus berupa digit tunggal, dan tidak dapat mengapung seperti 1.0dicampur. Juga, ini gagal pada daftar kosong, menghasilkan ].

Periksa negatif

Sekarang, untuk tugas non-string. Misalkan Anda memiliki daftar lbilangan real dan ingin menguji apakah itu berisi bilangan negatif, menghasilkan Boolean.

Anda dapat melakukan

'-'in`l`

yang memeriksa tanda negatif pada rep string. Ini lebih pendek dari salah satu dari

any(x<0for x in l)
min(l+[0])<0   

Untuk yang kedua, min(l)<0akan gagal pada daftar kosong, jadi Anda harus melakukan lindung nilai.


Pengikatan string digit tunggal juga efektif dalam Python 3, meskipun kurang: str(l)[2::5]adalah 12 byte, berbanding 19 untuk ''.join(map(str,l)). Situasi aktual di mana ini muncul (di mana lpernyataan generator, bukan daftar) menyelamatkan saya hanya satu byte ... yang masih layak!
Tim Pederick

25

Fungsi satu baris dapat dilakukan dengan lambda:

def c(a):
  if a < 3: return a+10
  else: return a-5

dapat dikonversi ke (perhatikan ruang yang hilang 3anddan 10or)

c=lambda a:a<3and a+10or a-5

21
atau c=lambda a:a+[-5,10][a<3]. trik dan / atau lebih berguna ketika Anda bergantung pada perilaku shortcircuit
gnibbler

3
Dalam fungsi Anda, else: bisa dijatuhkan sebagai returnmenghentikan eksekusi fungsi, jadi semua yang mengikuti hanya dieksekusi jika ifkondisinya gagal, alias jika elsekondisinya benar. Dengan demikian elsedapat dihilangkan dengan aman. (Dijelaskan secara terperinci untuk orang-orang baru di luar sana)
JeromeJ

c (-10) mengembalikan -15 sementara itu harus mengembalikan 0
Anvit

atauc=lambda a:a-5+15*(a<3)
JayXon

25

loop hingga 4 item mungkin lebih baik untuk memasok tuple daripada menggunakan rentang

for x in 0,1,2:

vs.

for x in range(3):

24

Ceil dan Lantai

Jika Anda ingin mendapatkan hasil pembulatan untuk divisi, seperti yang Anda lakukan dengan //lantai, Anda bisa menggunakan math.ceil(3/2)untuk 15 atau yang lebih pendek -(-3//2)untuk 8 byte.

math.floor(n)   : 13 bytes+12 for import
n//1            : 4  bytes

math.ceil(n)    : 12 bytes+12 for import
-(-n//1)        : 8  bytes

5
Ini baru saja menyelamatkan saya hampir 20 byte, terima kasih!
Morgan Thrapp

1
kadang-kadang Anda dapat pergi dengan n//1+1bukannya ceil tetapi itu berarti ceil (n) = n +1 tetapi itu harus bekerja untuk semua nilai non integer
fejfo

round(x)adalah (x+.5)//1, +1 byte tetapi yang terakhir dimulai dengan a (, dan jika xjumlah yang terdiri dari konstanta dapat berguna.
user202729

23

Gunakan +=sebagai ganti appenddanextend

A.append(B)  

dapat disingkat menjadi:

A+=B,

B,di sini membuat tupel satu elemen yang dapat digunakan untuk memperluas Aseperti [B]di A+=[B].


A.extend(B)

dapat disingkat menjadi:

A+=B

5
Dalam banyak (tetapi tidak semua) kasus, return 0atau return 1setara dengan return Falseatau return True.
undergroundmonorail

5
(1) hanya berfungsi jika Anda sudah tahu angkanya negatif, dalam hal ini Anda dapat menyimpan 2 karakter lebih lanjut hanya dengan menggunakan tanda minus. -xbukannya x*-1. --8.32bukannya -8.32*-1. Atau hanya 8.32...
trichoplax

Mengutip OP: Silakan kirim satu tip per jawaban.
nyuszika7h

Perhatikan bahwa dalam A+=B Badalah a tuple.
Erik the Outgolfer

23

Memilih satu dari dua angka berdasarkan suatu syarat

Anda sudah tahu untuk menggunakan pemilihan daftar [x,y][b]dengan Boolean buntuk ekspresi ternary y if b else x. Variabel x,, ydan bjuga bisa menjadi ekspresi, meskipun perhatikan bahwa keduanya xdan ydievaluasi bahkan ketika tidak dipilih.

Berikut beberapa potensi pengoptimalan kapan xdan ysedang angka.

  • [0,y][b] -> y*b
  • [1,y][b] -> y**b
  • [x,1][b] -> b or x
  • [x,x+1][b] -> x+b
  • [x,x-1][b] -> x-b
  • [1,-1][b] -> 1|-b
  • [x,~x][b] -> x^-b
  • [x,y][b] -> x+z*b(atau y-z*b), di mana z = yx.

Anda juga dapat beralih xdan yjika Anda dapat menulis ulang bmenjadi negasi sebagai gantinya.


22

Gunakan ~ untuk mengindeks dari bagian belakang daftar

Jika Ldaftar, gunakan L[~i]untuk mendapatkan ielemen 'th dari belakang.

Ini adalah ielemen kebalikan dari L. Bit komplemen ~isama dengan -i-1, dan memperbaiki kesalahan off-by-one dari L[-i].


21

PEP448 - Generalisasi Pembongkaran Tambahan

Dengan dirilisnya Python 3.5 , manipulasi daftar, tupel, set, dan dikt baru saja menjadi pemain golf.

Mengubah iterable menjadi set / list

Bandingkan pasangan:

set(T)
{*T}

list(T)
[*T]

tuple(T)
(*T,)

Jauh lebih pendek! Namun, perlu diketahui bahwa jika Anda hanya ingin mengonversi sesuatu ke daftar dan menetapkannya ke variabel, pembongkaran yang dapat diperpanjang yang normal lebih pendek:

L=[*T]
*L,=T

Sintaks yang sama berfungsi untuk tupel:

T=*L,

yang seperti diperpanjang membongkar iterable, tetapi dengan tanda bintang dan koma di sisi lain.

Bergabung daftar / tupel

Pembongkaran sedikit lebih pendek daripada penggabungan jika Anda perlu menambahkan daftar / tuple ke kedua sisi:

[1]+T+[2]
[1,*T,2]

(1,)+T+(2,)
(1,*T,2)

Mencetak isi beberapa daftar

Ini tidak terbatas pada print, tapi itu pasti dari mana sebagian besar jarak tempuh akan datang. PEP448 sekarang memungkinkan untuk beberapa pembongkaran, seperti:

>>> T = (1, 2, 3)
>>> L = [4, 5, 6]
>>> print(*T,*L)
1 2 3 4 5 6

Memperbarui beberapa item kamus

Ini mungkin tidak akan sering terjadi, tetapi sintaksis dapat digunakan untuk menghemat memperbarui kamus jika Anda memperbarui setidaknya tiga item:

d[0]=1;d[1]=3;d[2]=5
d={**d,0:1,1:3,2:5}

Ini pada dasarnya meniadakan kebutuhan dict.update.


6
Ini terlihat lebih buruk daripada Perl, tetapi berhasil ...
Mega Man

20

Ubah import *keimport*


Jika Anda belum pernah mendengar, import*simpan karakter!

from math import*

hanya 1 karakter lebih panjang dari import math as mdan Anda bisa menghapus semua instance darim.

Bahkan satu kali penggunaan adalah penghemat!


19
>>> for i in range(x):s+=input()

jika nilai saya tidak berguna:

>>> for i in[0]*x:s+=input()

atau

>>> exec's+=input();'*x

8
Anda dapat membuat contoh kedua for i in[0]*x:s+=input()untuk menghemat ruang lain. Selain itu, Anda dapat menghapus spasi antara eksekutif dan tanda kutip pertama untuk mendapatkannyaexec's+=input();'*x
Justin Peel

seharusnya baris kedua tidak menjadi:for i in[0]*x:s+=input()
micsthepick

Dupe (lebih baru tetapi lebih banyak upvotes)
user202729
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.