เคล็ดลับการตีกอล์ฟในไพ ธ อน


248

คุณมีเคล็ดลับทั่วไปสำหรับการเล่นกอล์ฟใน Python อย่างไร ฉันกำลังมองหาความคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟและอย่างน้อยก็ค่อนข้างเฉพาะเจาะจงกับ Python (เช่น "ลบความคิดเห็น" ไม่ใช่คำตอบ)

กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ


27
โอ้ฉันสามารถดูทั้งชุดของคำถามเช่นนี้มาสำหรับแต่ละภาษา ...
อาร์มาตินเฟอร์นันเด

4
@Marthinho ฉันเห็นด้วย เพียงแค่เริ่มต้นc ++ เทียบเท่า ฉันไม่คิดว่ามันเป็นสิ่งที่ไม่ดีตราบใดที่เราไม่เห็นคำตอบเดิมที่โพสต์ซ้ำในคำถามประเภทต่างๆเหล่านี้
Marcog

50
รักคำถาม แต่ฉันต้องบอกตัวเอง "นี่เป็นเพียงเพื่อความสนุกไม่ใช่รหัสการผลิต"
Greg Guida

2
คำถามนี้ไม่ควรเป็นโพสต์ของวิกิชุมชนหรือไม่
dorukayhan

3
@Dorukayhan Nope; เป็นคำถามเคล็ดลับcode-golf ที่ ถูกต้องถามเคล็ดลับในการย่อpython code เพื่อจุดประสงค์ในการ CG คำถามดังกล่าวใช้ได้อย่างสมบูรณ์แบบสำหรับเว็บไซต์และไม่มีแท็กเหล่านี้อย่างชัดเจนว่าคำถามนั้นควรเป็น CW'd ซึ่งไม่เหมือนกับ SO ซึ่งจำเป็นต้องใช้ความท้าทาย CG ในการเป็น CW'd นอกจากนี้การเขียนคำตอบที่ดีและการค้นหาเคล็ดลับดังกล่าวควรได้รับบางสิ่งบางอย่างเสมอซึ่งจะถูกนำไปใช้หากคำถามคือวิกิชุมชน (ตัวแทน)
Erik the Outgolfer

คำตอบ:


152

ใช้แทนa=b=c=0a,b,c=0,0,0

ใช้แทนa,b,c='123'a,b,c='1','2','3'


2
เป็นคำแนะนำที่ดีโดยทั่วไป :)

28
โปรดทราบว่าการดำเนินการนี้ไม่จำเป็นสำหรับการกำหนดวัตถุที่ไม่แน่นอนซึ่งคุณจะทำการแก้ไขแทน a = b = [1] แตกต่างจาก a = [1]; b = [1]
isaacg

6
สิ่งที่ตลกเกี่ยวกับเคล็ดลับแรกคือมันใช้งานได้ใน Java เช่นกัน
Justin

1
@Justin ใช่ แต่มีเฉพาะประเภทดั้งเดิม
HyperNeutrino

11
แต่ไม่ควรใช้ a = b = c = [] หรือการติดตั้งวัตถุใด ๆ เนื่องจากตัวแปรทั้งหมดจะชี้ไปที่อินสแตนซ์เดียวกัน นั่นอาจไม่ใช่สิ่งที่คุณต้องการ
PhE

146

เงื่อนไขอาจมีความยาว ในบางกรณีคุณสามารถแทนที่เงื่อนไขแบบง่าย(a,b)[condition]ได้ หากconditionเป็นจริงbจะถูกส่งคืน

เปรียบเทียบ

if a<b:return a
else:return b

สำหรับสิ่งนี้

return(b,a)[a<b]

37
สิ่งเหล่านี้ไม่เหมือนกัน คนแรกประเมินเฉพาะการแสดงออกที่ถูกส่งกลับในขณะที่คนที่สองมักจะประเมินพวกเขาทั้งสอง สิ่งเหล่านี้ทำให้เกิดการลัดวงจรa if a<b else bและa<b and a or b
marinus

3
(lambda(): b, lambda(): a)[a < b]()ทำลัดวงจรของคุณเองด้วย lambdas
Ming-Tang

3
@marinus พวกเขาจะไม่เท่ากัน: เพียงแค่พิจารณาP and A or Bของ A ใด ๆ bool(A)=Falseที่ทำให้ แต่(P and [A] or [B])[0]จะทำหน้าที่ ดูdiveintopython.net/power_of_introspection/and_or.htmlสำหรับการอ้างอิง
kgadek

6
แลมบ์ดามีความยาวกว่านิพจน์เงื่อนไข
user2357112

18
@ user2357112 แต่พวกเขาทำให้คุณดูเท่ห์กว่าเมื่อคุณใช้งาน :]
Chase Ries

117

สิ่งที่ยอดเยี่ยมที่ฉันเคยทำครั้งเดียวคือ:

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

แทน:

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

ตัวดำเนินการเปรียบเทียบของ Python ร็อค


การใช้สิ่งนั้นเปรียบได้กับ Python 2 คุณสามารถหลีกเลี่ยงตัวandดำเนินการนี้ได้ ตัวอย่างเช่นถ้าa, b, cและdเป็นจำนวนเต็ม

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

สามารถย่อให้สั้นลงโดยอักขระหนึ่งตัวไปที่:

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

สิ่งนี้ใช้ว่าทุกรายการมีขนาดใหญ่กว่าจำนวนเต็มใด ๆ

หากcและdเป็นรายการสิ่งนี้จะดีขึ้นกว่าเดิม:

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

22
แน่นอนว่าถ้ามันถูกตีกอล์ฟจริงๆมันก็จะเป็น3>a>1<b<5
Rafe Kettler

4
รักความสมมาตร ทำให้ผมนึกถึงเก่า Perl เคล็ดลับกอล์ฟสำหรับการค้นหานาทีของ $ และ $ b: [$a => $b]->[$b <= $a]:)
ไซมอนวิทเทเกอร์

โปรดทราบว่าตัวอย่างที่สอง (ไม่มีรายการ) สามารถทำได้ด้วยif(a<b)+(c>d):foo()
WorldSEnder

6
+ *ที่ควรจะเป็น orจะเป็น+
WorldSEnder

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

103

หากคุณกำลังใช้ฟังก์ชั่นในตัวซ้ำ ๆ อาจเป็นพื้นที่ที่มีประสิทธิภาพมากขึ้นในการตั้งชื่อใหม่หากใช้อาร์กิวเมนต์ที่ต่างกัน:

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

6
แม้ว่าจะไม่ได้บันทึกไบต์ใด ๆ จริง ๆ
user2357112

4
r = range และอีกสอง r's คือ 9 ตัวอักษร; ใช้ช่วงสองครั้งคือ 10 ตัวอักษร ไม่ใช่การออมขนาดใหญ่ในตัวอย่างนี้ แต่สิ่งที่ต้องทำทั้งหมดคือการใช้ช่วงเพิ่มเติมเพื่อดูการประหยัดที่สำคัญ
แฟรงค์

13
@Frank บรรทัดใหม่เพิ่มเติมเป็นตัวละครอื่น
L3viathan

2
แน่นอนว่าการซ้ำสองครั้งนั้นน้อยเกินไปที่จะบันทึกชื่อฟังก์ชั่นความยาวห้าชื่อ คุณต้องการ: ความยาว 2: 6 reps, ความยาว 3: 4 reps, ความยาว 4 หรือ 5: 3 reps, ความยาว> = 6: 2 reps AKA (length-1) * (reps-1)> 4
Ørjan Johansen

หมายเหตุนี่ใช้ได้กับทุกภาษาที่มีฟังก์ชั่นชั้นหนึ่ง
bfontaine

94

บางครั้งรหัส Python ของคุณกำหนดให้คุณมีการเยื้อง 2 ระดับ สิ่งที่ชัดเจนที่ต้องทำคือใช้ช่องว่างหนึ่งและสองช่องสำหรับแต่ละระดับของการย่อหน้า

อย่างไรก็ตาม Python 2 พิจารณาว่าแท็บและอักขระเว้นวรรคเป็นระดับการเยื้องที่แตกต่างกัน

ซึ่งหมายความว่าระดับการเยื้องครั้งแรกสามารถเป็นหนึ่งช่องว่างและระดับที่สองสามารถเป็นหนึ่งอักขระแท็บ

ตัวอย่างเช่น:

if 1:
 if 1:
\tpass

\tอักขระแท็บอยู่ที่ไหน


1
เยี่ยมเลยฉันไม่เคยคิดถึงเรื่องนี้เลย!
Jules Olléon

97
สิ่งนี้ล้มเหลวใน python3: คุณไม่สามารถผสมช่องว่างและแท็บได้อีกต่อไป (เป็นสิ่งเลวร้ายสำหรับ codegolf แต่เป็นสิ่งที่ดีในกรณีอื่น ๆ ทั้งหมด)
Bakuriu

1
ใน python 3.4 มันทำงานได้ดี
trichoplax

3
@trichoplax , ในไพ ธ อน 3.4.3 ฉันได้รับTabError: inconsistent use of tabs and spaces in indentation.
ceilingcat

สำหรับการอ้างอิงแท็บมีค่าเท่ากับ 8 ช่องว่าง
Erik the Outgolfer

87

ใช้การแทนที่สตริงและexecเพื่อจัดการกับคำหลักที่ยาวเช่นlambdaนี้ซ้ำแล้วซ้ำอีกในรหัสของคุณ

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  (%)

สตริงเป้าหมายบ่อยมาก'lambda 'ซึ่งมีความยาว 7 ไบต์ สมมติว่าโค้ดของคุณมีnปรากฏของ'lambda 'และเป็นsเวลานานไบต์ แล้ว:

  • plainตัวเลือกsไบต์นาน
  • replaceตัวเลือกs - 6n + 29ไบต์นาน
  • %ตัวเลือกs - 5n + 22 + len(str(n))ไบต์นาน

จากพล็อตของไบต์ที่บันทึกไว้plainสำหรับตัวเลือกทั้งสามนี้เราจะเห็นว่า:

  • สำหรับn <5 lambdas คุณไม่ควรทำอะไรแฟนซีเลย
  • สำหรับn = 5การเขียนexec"..."%(('lambda ',)*5)จะบันทึก 2 ไบต์และเป็นตัวเลือกที่ดีที่สุดของคุณ
  • สำหรับn> 5การเขียนexec"...".replace('`','lambda ')เป็นตัวเลือกที่ดีที่สุดของคุณ

สำหรับกรณีอื่น ๆ คุณสามารถจัดทำดัชนีตารางด้านล่าง:

          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)

ตัวอย่างเช่นถ้าสตริงlambda x,y:(ความยาว 11) เกิดขึ้น 3 exec"..."%(('lambda x,y:',)*3)ครั้งในรหัสของคุณคุณก็ยังดีเขียน


4
นี่ควรได้รับคะแนนโหวตเพิ่มขึ้นซึ่งเป็นเคล็ดลับที่มีประโยชน์มาก
bigblind

7
มันหายากมากที่ใช้งานได้ ค่าใช้จ่ายสูงreplaceมาก
บูธตาม

4
เมื่อมันได้ผลก็ช่วยได้มาก
undergroundmonorail

ที่น่าสนใจไม่เคยคิดเรื่องนี้เลย!
Claudiu

ฉันจะเพิ่มผู้ประกอบการใหม่สำหรับแลมบ์ดาในภาษาของฉันตามออกของงูหลาม: เป็นเพียงสตริง=> = lambda ยกตัวอย่างเช่นจะเป็นf=>:0 f = lambda: 0
NoOneIsHere

78

ใช้การแบ่งส่วนเพิ่มเติมเพื่อเลือกหนึ่งสตริงจากหลาย ๆ สตริง

>>> 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

ในกรณีที่สองสตริงบูลีนนี้หนึ่งสามารถเขียน

b*"string"or"other_string"

สำหรับ

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

ซึ่งแตกต่างจาก interleaving สิ่งนี้ใช้ได้กับสตริงที่มีความยาวเท่าใดก็ได้ แต่อาจมีปัญหาที่สำคัญกว่าตัวดำเนินการหากbเป็นนิพจน์แทน


โปรดทราบว่าตัวอย่างแรกมีความยาวเท่ากับfor x in ("foo","bar","baz"): print x
Mateen Ulhaq

1
@MateenUlhaq, นั่นเป็นเพียงตัวอย่างของวิธีการที่ค่าที่แตกต่างจากการxแสดงผล ส่วน golfed คือ"fbboaaorz"[x::3]vs ["foo","bar","baz"][x]วิธีที่xได้รับค่าจะเป็นอีกส่วนหนึ่งของการแก้ปัญหากอล์ฟของคุณ
gnibbler

72

ใช้`n`เพื่อแปลงจำนวนเต็มเป็นสตริงแทนที่จะใช้str(n):

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

38
ดีมาก แต่ใช้งานไม่ได้กับ Python3
Alexandru

2
ข้อควรสนใจ: ใช้งานได้จริงสำหรับจำนวนเต็ม แต่ไม่ใช่สำหรับสตริงตัวอย่างเช่น
Nakilon

41
BTW `` ย่อมาจากคำพิพากษา
Alexandru

9
จำนวนเต็มที่น้อยกว่า -2 ** 31 หรือใหญ่กว่า 2 ** 31-1 (Longs) จะได้รับ 'L' ที่ติดอยู่ในตอนท้าย
hallvabo

6
นอกจากนี้ยังสามารถใช้ในการพิมพ์ลอยเพื่อความแม่นยำเต็ม
gnibbler

69

จัดเก็บตารางการค้นหาเป็นตัวเลขเวทย์มนตร์

สมมติว่าคุณต้องการที่จะ hardcode 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

จากนั้นคุณสามารถใช้ตารางการค้นหานี้อย่างกระชับเป็น:

3714>>i&1

กับที่เกิดขึ้น0หรือ1เท่ากับไปFalseTrue

แนวคิดคือหมายเลขมายากลเก็บตารางเป็น bitstring bin(3714)= 0b111010000010โดยมีตัวเลขn-th (จากท้าย) ตรงกับnรายการตารางที่ เราเข้าถึงnรายการ TH โดย bitshifting จำนวนช่องว่างที่เหมาะสมและการใช้หลักสุดท้ายโดยn&1

วิธีการเก็บรักษานี้มีประสิทธิภาพมาก เปรียบเทียบกับทางเลือกอื่น

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

คุณสามารถมีตารางการค้นหาที่เก็บหลายรายการที่สามารถแยกได้เช่น

 340954054>>4*n&15

เพื่อแยกบล็อกสี่บิตที่เกี่ยวข้อง


เราสามารถมีตัวอย่างผลสำหรับบล็อกสี่บิตได้หรือไม่? คุณใช้กฎสำหรับบล็อก n-bit หรือไม่?
JeromeJ

8
Hex บางครั้งอาจมีขนาดเล็กลง
Joonazan

4
สิ่งนี้มีประโยชน์สำหรับหลายภาษา
Cyoce

1
@Joonazan Hex มีขนาดเล็กสำหรับตัวเลขมากกว่า999 999
Mateen Ulhaq

60

ยุบลูปตัวเลขสองวงเป็นหนึ่ง

สมมติว่าคุณวนซ้ำเซลล์ของm*nกริด แทนที่จะเป็นสองforวงซ้อนกันสองวงหนึ่งแถวและหนึ่งคอลัมน์โดยปกติแล้วจะสั้นกว่าเมื่อใช้วงเดียวเพื่อวนซ้ำไปยังm*nเซลล์ของตาราง คุณสามารถแยกแถวและคอลัมน์ของเซลล์ภายในลูป

รหัสเดิม:

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

รหัส Golfed:

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

ผลที่คุณกำลังทำซ้ำมากกว่าผลิตภัณฑ์ Cartesian ของทั้งสองช่วงการเข้ารหัสทั้งคู่เป็น(i,j) x=i*n+jคุณได้บันทึกการrangeโทรที่มีค่าใช้จ่ายและระดับของการเยื้องในลูป ลำดับของการวนซ้ำไม่เปลี่ยนแปลง

ใช้//แทน/ในหลาม 3. ถ้าคุณอ้างถึงiและjหลายครั้งก็อาจจะได้เร็วขึ้นในการกำหนดค่าของพวกเขาi=k/n, j=k%nภายในวง


5
นี่มันเจ๋งมาก. ฉันไม่เคยรู้เลยว่ามันเป็นไปได้!
theonlygusti

ฉันเห็นสิ่งนี้ในเคล็ดลับสำหรับ JavaScript มันเป็นเคล็ดลับที่มีประโยชน์ในภาษาส่วนใหญ่
Cyoce

7
สำหรับการอ้างอิงเพื่อขยายสิ่งนี้เป็น 3 ลูป:for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o)
mbomb007

3
สำหรับnลูป: repl.it/EHwa
mbomb007

ในบางกรณีitertools.productสามารถรัดกุมมากกว่าลูปซ้อนโดยเฉพาะเมื่อสร้างผลิตภัณฑ์คาร์ทีเซียน a1, a2, b1, b2เป็นตัวอย่างของผลิตภัณฑ์คาร์ทีเซียนของ'ab'และ'12'
Aaron3468

54

เว้นแต่โทเค็นต่อไปนี้เริ่มต้นด้วยหรือe Eคุณสามารถลบช่องว่างตามหมายเลข

ตัวอย่างเช่น

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

กลายเป็น:

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

การใช้สิ่งนี้ในข้อความสั่งบรรทัดเดียวที่ซับซ้อนสามารถบันทึกอักขระได้ไม่กี่ตัว

แก้ไข: ตามที่ @marcog ชี้ให้เห็นว่า4or aจะใช้งานได้ แต่ไม่ใช่a or4เมื่อสิ่งนี้สับสนกับชื่อตัวแปร


37
if(i,j)==(4,4):สั้นลงและในกรณีพิเศษนี้if i==j==4:
gnibbler

3
ที่เกี่ยวข้อง: ใช้4or aงานได้ แต่ไม่ใช่a or4
marcog

17
0orยังไม่ทำงาน ( 0oเป็นคำนำหน้าสำหรับหมายเลขฐานแปด)
Nabb

5
@Nabb ไม่ว่าจะเป็นเรื่องสำคัญเพราะ0 or xจะกลับมาxเสมอ อาจจะถูกตัดออก0 orไป
Aprıʇǝɥʇuʎs

5
0orเป็นเรื่องปกติเนื่องจากเป็นส่วนหนึ่งของจำนวนที่นานกว่า เทียบเท่ากับ10 or x 10or x
trichoplax

53

สำหรับจำนวนเต็มnคุณสามารถเขียน

  • n+1 เช่น -~n
  • n-1 เช่น ~-n

เพราะบิตพลิกเท่ากับ~x -1-xสิ่งนี้ใช้จำนวนอักขระเท่ากัน แต่สามารถตัดช่องว่างหรือการเว้นวรรคทางอ้อมสำหรับลำดับความสำคัญของโอเปอเรเตอร์

เปรียบเทียบ:

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

ผู้ประกอบการ~และเอก-มีความสำคัญสูงกว่า*, /, ซึ่งแตกต่างจากไบนารี%+


11
รูปแบบที่หลากหลายเคล็ดลับนี้ฉันวิ่งเข้าไปในวันนี้: บันทึกหนึ่งไบต์เทียบกับ-~-x (1-x)
Lynn

4
แอปพลิเคชั่นที่มีประโยชน์อีกอย่างหนึ่งนั้นa+b+1สามารถเขียนได้กระชับa-~bกว่า
Strigoides

และเป็นเพียงn-i-1 n+~i
ruohola

51

วิธีที่ดีในการแปลง iterable เป็นรายการในPython 3 :

จินตนาการว่าคุณมีบางอย่างซ้ำแล้วซ้ำอีกเช่น

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

แต่คุณต้องการรายการ:

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

มันมีประโยชน์มากในการสร้างรายการตัวอักษรจากสตริง

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

1
พิมพ์*s,='abcde'แล้วsขัดข้อง python3 แบบโต้ตอบของฉันด้วย segfault :(
daniero

@daniero ว้าว บนคอนโซลแบบโต้ตอบเท่านั้น ฟังดูแปลกมาก ลองทำความสะอาดคอนโซลหรือรายงานข้อผิดพลาด
JBernardo

1
Python 3.5 ของฉันทำงานได้ดี
NoOneIsHere

สำหรับ i = (x ** 2 สำหรับ x ในช่วง (5)) ฉันได้รับรหัสนี้คืน <generator object <genexpr> ที่ 0x03321690>
george

7
[*'abcde']และถ้าคุณทำเช่นนี้ในการแสดงออกที่คุณสามารถทำได้
ผลไม้แยกแยะ

46

แทนที่จะrange(x)ใช้คุณสามารถใช้*โอเปอเรเตอร์ในรายการของสิ่งใดก็ได้หากคุณไม่จำเป็นต้องใช้ค่าของi:

for i in[1]*8:pass

ตรงข้ามกับ

for i in range(8):pass

หากคุณต้องการทำสิ่งนี้มากกว่าสองครั้งคุณสามารถกำหนดตัวแปรที่สามารถทำซ้ำได้ให้กับตัวแปรแล้วคูณตัวแปรนั้นด้วยช่วงที่คุณต้องการ:

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

หมายเหตุ : นี่มักจะยาวกว่าexec"pass;"*8ดังนั้นเคล็ดลับนี้ควรใช้เฉพาะเมื่อไม่มีตัวเลือก


@proudhaskeller ฉันคิดว่าจุดของบรรทัดที่คุณลบออกคือ "นอกจากการประหยัดอักขระที่เห็นได้ชัดที่คุณได้รับเพราะ[1]*8สั้นกว่าrange(8)คุณยังประหยัดพื้นที่เพราะfor i in[...ถูกกฎหมายในขณะที่for i in range...ไม่ถูกต้อง"
undergroundmonorail

โอ้ใช่ฉันไม่เข้าใจ แก้ไขแล้ว
ภูมิใจ haskeller

7
exec"pass;"*8สั้นกว่ามาก
DJMcMayhem

1
ถ้าr=1, r*88, และคุณไม่สามารถย้ำผ่านหมายเลข ฉันเดาว่าคุณหมายถึงr=[1]
Artemis Fowl

1
@ ArtemisFowl ไม่เป็นไรเครื่องหมายคอมม่าหลังจากที่ 1 สร้าง tuple ซึ่งสามารถทำซ้ำได้
sasha

43

คุณสามารถใช้รูปหน้ายิ้มเอเลี่ยนตัวเก่าเพื่อย้อนกลับลำดับ:

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

38

ขยายการบรรจุซ้ำ ("การมอบหมายที่ติดดาว", Python 3 เท่านั้น)

วิธีที่ดีที่สุดในการอธิบายสิ่งนี้คือผ่านตัวอย่าง:

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

เราได้เห็นการใช้งานนี้แล้ว - เปลี่ยน iterable เป็นรายการใน Python 3 :

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

นี่คือการใช้งานเพิ่มเติมไม่กี่อย่าง

รับองค์ประกอบสุดท้ายจากรายการ

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

ในบางสถานการณ์สิ่งนี้สามารถใช้ในการรับองค์ประกอบแรกเพื่อประหยัด parens:

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

การกำหนดรายการว่างและตัวแปรอื่น ๆ

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

การลบองค์ประกอบแรกหรือสุดท้ายของรายการที่ไม่ว่างเปล่า

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

เหล่านี้จะสั้นกว่าทางเลือกและL=L[1:] L.pop()สามารถบันทึกผลลัพธ์ไปยังรายการอื่นได้

เคล็ดลับมารยาทของ @grc


ว้าว! ฉันได้เขียนa=1;L=[]หลายครั้ง มันวิเศษมากที่คุณสามารถบันทึกตัวอักษรลงบนสิ่งที่ตรงไปตรงมาเช่นนี้
xnor

@ xnor ขอบคุณสำหรับ GRC มีเพียงหนึ่งองค์ประกอบอื่น ๆ ก็ไม่ดี ( a,*L=1,) แต่ก็ยังช่วยประหยัดถ่านหนึ่ง :)
SP3000

อย่าลืมว่าคุณยังสามารถรับทั้งรายการแรกและรายการสุดท้ายด้วยa,*_,b=L
Cyoce

36

ตั้งค่าตัวอักษรใน Python2.7

คุณสามารถเขียนชุดเช่นนี้S={1,2,3}ซึ่งหมายความว่าคุณสามารถตรวจสอบการเป็นสมาชิกโดยใช้{e}&Sแทนการe in Sบันทึกอักขระหนึ่งตัว


4
และนี้ยังช่วยประหยัดตัวละครในifฐานะไม่มีช่องว่าง ( if{e}&S:)
Artyer

1
โปรดทราบว่าคุณสามารถแทนที่not inโดย{e}-Sมีเคล็ดลับที่
ดำนกฮูกไก่

35

สำหรับทุกวัยมันทำให้ฉันรำคาญที่ฉันไม่สามารถคิดถึงวิธีสั้น ๆ ในการรับตัวอักษรทั้งหมด หากคุณใช้rangeเพียงพอที่R=rangeมีค่าในโปรแกรมของคุณแล้ว

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

สั้นกว่าความไร้เดียงสา

'abcdefghijklmnopqrstuvwxyz'

แต่อย่างอื่นมันมีความยาวมากกว่าตัวอักษรตัวเดียว มันหลอกหลอนฉันว่าคนฉลาดที่ต้องการความรู้เกี่ยวกับคุณค่าของ ASCII นั้นจบลงด้วยความละเอียดมากกว่าแค่พิมพ์ตัวอักษรทั้งหมด

จนกระทั่งผมเห็นนี้คำตอบสำหรับลูกสาวของฉันตัวอักษร ฉันไม่สามารถติดตามประวัติการแก้ไขได้ดีพอที่จะคิดได้ว่าอัจฉริยะนี้เป็นผลงานของ OP หรือถ้าเป็นคำแนะนำจากผู้แสดงความคิดเห็น แต่นี่คือ (ฉันเชื่อ) วิธีที่สั้นที่สุดในการสร้างตัวอักษร 26 ตัวที่น่าสนใจ ในอักษรโรมัน

map(chr,range(97,123))

หากกรณีไม่สำคัญคุณสามารถตัดอักขระอื่นโดยใช้ตัวพิมพ์ใหญ่

map(chr,range(65,91))

ฉันใช้mapวิธีมากเกินไปฉันไม่รู้ว่าสิ่งนี้ไม่เคยเกิดขึ้นกับฉัน


4
อาจใช้สิ่งนี้ในการเขียนรหัสจริงฉันรู้สึกงี่เง่าเมื่อทำการเข้ารหัสสิ่งเหล่านี้: ')
ToonAlfrink

37
ในการเขียนโค้ดจริงใช้string.lowercase- นั่นคือสิ่งที่มันมีไว้สำหรับ
Kevin S

1
หากคุณต้องการทั้งสองกรณีวิธีที่สั้นที่สุดที่ฉันรู้คือตัวกรอง (str.isalpha, map (chr, range (256))) มันเพิ่งจะสั้นกว่า s = map (chr, range (256)); s + = map (str.lower, s)
quintopia

@quintopia: ทำไม 256 แทน 122 ( ord('z')) นอกเหนือจากมันเป็นระยะเวลาเดียวกัน ... นอกจากนี้ถ้าคุณต้องการ Alphanumerics แทนstr.isalphaในรุ่นของ @ quintopia str.isalnumกับ (แต่ถ้าคุณต้องการเพียงหนึ่งกรณีสตริง 36 อักขระทั้งหมดไม่เกินfilter(str.isalnum,map(chr,range(90))))
Tim Pederick

2
หากคุณจะไม่ยุติธรรมและใช้ช่วงเป็นRรุ่นของฉันจะสั้นกว่าเดิมของคุณ: '%c'*26%tuple(R(97,123))(เพียง 24 ตัวอักษร) ถ้าคุณสะกดrangeมันเป็นเพียงตราบใดที่ตัวอักษร - รุ่นตัวพิมพ์ใหญ่จะสั้นกว่า
JBernardo

32

แม้ว่าหลามจะไม่มีคำสั่งสลับคุณสามารถเลียนแบบพวกเขาด้วยพจนานุกรม ตัวอย่างเช่นหากคุณต้องการสวิตช์แบบนี้:

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

คุณสามารถใช้ifคำสั่งหรือคุณสามารถใช้สิ่งนี้:

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

หรือสิ่งนี้:

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

ซึ่งจะดีกว่าถ้าพา ธ โค้ดทั้งหมดเป็นฟังก์ชันที่มีพารามิเตอร์เดียวกัน

เพื่อรองรับค่าเริ่มต้นให้ทำสิ่งนี้:

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

(หรือนี่ :)

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

ข้อดีอีกอย่างหนึ่งของสิ่งนี้คือถ้าคุณมีการทำซ้ำซ้อนคุณสามารถเพิ่มพวกมันหลังจากสิ้นสุดพจนานุกรม:

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

และถ้าคุณต้องการใช้สวิตช์เพื่อคืนค่า:

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

คุณสามารถทำสิ่งนี้ได้:

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

2
นี่คือสิ่งที่ฉันจะพิจารณาอย่างลึกซึ้งในการใช้งานในป่า ฉันทำพลาดงบสวิตช์ของฉัน! +1
HalosGhost

1
แม้ว่าแทนที่จะใช้พจนานุกรมที่มีคีย์ตัวเลขในตัวอย่างแรกคุณควรใช้รายการ
Cyoce

1
หากคุณมีสตริงเป็นคีย์ให้ใช้dict(s1=v1,s2=v2,...,sn=vn)แทนการ{'s1':v1,'s2':v2,...,'sn':vn}บันทึก 2 * n-4 ไบต์และจะดีกว่าถ้า n> = 3
Black Owl Kai

31

เมื่อคุณมีสองค่าบูลีนaและbถ้าคุณต้องการที่จะหาถ้าทั้งสองaและbเป็นจริงใช้*แทนand:

if a and b: #7 chars

VS

if a*b: #3 chars

ถ้าค่าใดค่าหนึ่งเป็นเท็จมันจะประเมินดังเช่น0ในคำสั่งนั้นและค่าจำนวนเต็มจะเป็นจริงเฉพาะในกรณีที่ไม่ใช่ค่าศูนย์


9
หรือคุณสามารถใช้&: a=b=False,a&b
ɐɔıʇǝɥʇuʎs

3
ใช้+สำหรับorหากคุณสามารถรับประกันได้a != -b
undergroundmonorail

2
|ทำงานได้ในทุกสถานการณ์
CalculatorFeline

1
*แทนand/ &&บันทึกบางไบต์ในหลายภาษา
สูญเปล่า

26

ใช้ประโยชน์จากการเป็นตัวแทนของ Python 2

Python 2 ช่วยให้คุณแปลงวัตถุxเป็นตัวแทนสตริง`x`ได้ด้วยราคาเพียง 2 ตัวอักษร ใช้สิ่งนี้สำหรับงานที่ทำได้ง่ายกว่าบนสตริงของวัตถุมากกว่าวัตถุ

เข้าร่วมตัวละคร

รับรายชื่อตัวละครl=['a','b','c']หนึ่งสามารถสร้าง''.join(l)เป็น`l`[2::5]ซึ่งบันทึกไบต์

เหตุผลก็`l`คือ "['a', 'b', 'c']"(พร้อมช่องว่าง) เพื่อให้หนึ่งสามารถแยกตัวอักษรที่มีชิ้นรายการเริ่มต้นที่ตัวอักษรศูนย์ zeroed ตัวที่สองaและนำตัวละครที่ห้าทุกจากที่นั่น '\n'นี้ไม่ได้ทำงานที่จะเข้าร่วมสตริงหลายตัวละครหรือตัวหนีตัวแทนเช่น

เชื่อมโยงตัวเลข

ในทำนองเดียวกันการกำหนดรายการที่ไม่ว่างเปล่าของตัวเลขเช่นl=[0,3,5]หนึ่งสามารถเชื่อมให้เป็นสตริงเป็น'035'`l`[1::3]

map(str,l)นี้ช่วยประหยัดทำสิ่งที่ต้องการ โปรดทราบว่าพวกเขาจะต้องหลักเดียวและไม่สามารถมีลอยเหมือน1.0ผสม. นอกจากนี้ล้มเหลวในรายการที่ว่างเปล่า, ]การผลิต

ตรวจสอบเชิงลบ

ตอนนี้สำหรับงานที่ไม่ใช่สตริง สมมติว่าคุณมีรายการlตัวเลขจริงและต้องการทดสอบว่ามีจำนวนลบใด ๆ หรือไม่สร้างบูลีน

คุณทำได้

'-'in`l`

ซึ่งตรวจสอบเครื่องหมายลบในตัวแทนสตริง นี้สั้นกว่าอย่างใดอย่างหนึ่ง

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

สำหรับครั้งที่สองmin(l)<0จะล้มเหลวในรายการว่างดังนั้นคุณต้องป้องกันความเสี่ยง


เชื่อมโยงเดียวหั่นสตริงตัวเลขยังมีประสิทธิภาพในหลาม 3 แม้จะน้อยดังนั้น: str(l)[2::5]12 ไบต์เมื่อเทียบกับ ''.join(map(str,l))19 สถานการณ์จริงที่เกิดขึ้น (ซึ่งlเป็นคำสั่งเครื่องกำเนิดไม่รายการ) บันทึกฉันเพียงหนึ่งไบต์ ... ซึ่งยังคงคุ้มค่า!
ทิม Pederick

25

ฟังก์ชั่นหนึ่งบรรทัดสามารถทำได้ด้วยแลมบ์ดา:

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

สามารถแปลงเป็น (หมายเหตุช่องว่างที่ขาดหายไป3andและ10or)

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

21
c=lambda a:a+[-5,10][a<3]หรือ และ / หรือเคล็ดลับมีประโยชน์มากขึ้นเมื่อคุณขึ้นอยู่กับพฤติกรรม
shortcircuit

3
ในฟังก์ชั่นของคุณelse: สามารถลดลงได้เมื่อreturnหยุดการทำงานของฟังก์ชั่นดังนั้นทุกอย่างที่ตามมาจะถูกดำเนินการเฉพาะในกรณีที่ifเงื่อนไขล้มเหลวหรือหาก elseเงื่อนไขเป็นจริง ดังนั้นelseสามารถ ommited อย่างปลอดภัย (อธิบายโดยละเอียดสำหรับ
เซลล์เม็ดเลือดขาวที่

c (-10) ส่งกลับค่า -15 ในขณะที่ควรคืนค่า 0
Anvit

หรือc=lambda a:a-5+15*(a<3)
JayXon

25

การวนซ้ำสูงสุด 4 รายการอาจเป็นการดีกว่าที่จะจัดหา tuple แทนที่จะใช้ช่วง

for x in 0,1,2:

VS

for x in range(3):

24

เพดานและพื้น

หากคุณต้องการรับผลการปัดเศษสำหรับการแบ่งเช่นเดียวกับที่คุณทำกับ//พื้นคุณสามารถใช้math.ceil(3/2)15 หรือสั้นกว่านั้น-(-3//2)เป็น 8 ไบต์

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
นี่เพิ่งช่วยฉันเกือบ 20 ไบต์ขอบคุณ!
Morgan Thrapp

1
บางครั้งคุณสามารถออกไปn//1+1แทนที่จะเป็น ceil แต่มันหมายถึง ceil (n) = n + 1 แต่มันควรใช้ได้กับค่าที่ไม่ใช่จำนวนเต็มทั้งหมด
fejfo

round(x)คือ(x+.5)//1+1 ไบต์ แต่หลังเริ่มต้นด้วย a (และถ้าxเป็นผลรวมประกอบด้วยค่าคงที่จะมีประโยชน์
user202729

23

ใช้+=แทนappendและextend

A.append(B)  

สามารถย่อให้เหลือ:

A+=B,

B,ที่นี่สร้าง tuple หนึ่งองค์ประกอบที่สามารถนำมาใช้ในการขยายAเช่นเดียวกับใน[B]A+=[B]


A.extend(B)

สามารถย่อให้เหลือ:

A+=B

5
ในหลาย ๆ ( แต่ไม่ใช่ทั้งหมด) กรณีreturn 0หรือreturn 1เทียบเท่ากับหรือreturn False return True
undergroundmonorail

5
(1) ใช้งานได้ก็ต่อเมื่อคุณทราบว่าหมายเลขนั้นเป็นค่าลบซึ่งในกรณีนี้คุณสามารถบันทึกอักขระเพิ่มเติมได้อีก 2 ตัวโดยใช้เครื่องหมายลบ มากกว่า-x มากกว่า หรือเพียงแค่...x*-1--8.32-8.32*-18.32
trichoplax

Quoting the OP: กรุณาโพสต์หนึ่งคำตอบต่อคำตอบ
nyuszika7h

หมายเหตุในการที่เป็นA+=B B tuple
Erik the Outgolfer

23

เลือกหนึ่งในสองตัวเลขตามเงื่อนไข

คุณรู้แล้วว่าใช้การเลือกรายการ[x,y][b]ด้วย Boolean bสำหรับนิพจน์ประกอบy if b else xไปด้วย ตัวแปรx, yและbยังสามารถที่จะแสดงออก แต่ทราบว่าทั้งสองxและyมีการประเมินแม้ในขณะที่ไม่ได้เลือก

นี่คือการเพิ่มประสิทธิภาพที่เป็นไปได้เมื่อxและyเป็นตัวเลข

  • [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(หรือy-z*b) โดยที่ z = yx

นอกจากนี้คุณยังสามารถสลับxและyหากคุณสามารถเขียนใหม่bเพื่อให้ปฏิเสธได้


22

ใช้ ~ เพื่อจัดทำดัชนีจากด้านหลังของรายการ

หากLเป็นรายการให้ใช้L[~i]เพื่อรับiองค์ประกอบ 'จากด้านหลัง

นี่คือ'องค์ประกอบของวันกลับของi Lบิตสมบูรณ์~iเท่ากับและเพื่อแก้ไขข้อผิดพลาดออกโดยหนึ่งจาก -i-1L[-i]


21

PEP448 - ลักษณะทั่วไปของการเปิดออกเพิ่มเติม

ด้วยการเปิดตัวPython 3.5 การจัดการรายการ tuples ชุดและ dicts ก็จะกลายเป็นนักกอล์ฟ

เปลี่ยน iterable เป็นชุด / รายการ

เปรียบเทียบคู่:

set(T)
{*T}

list(T)
[*T]

tuple(T)
(*T,)

สั้นกว่ามาก! แต่โปรดทราบว่าถ้าคุณเพียงต้องการที่จะแปลงบางสิ่งบางอย่างไปยังรายการและกำหนดให้ตัวแปรปกติขยายการเปิดออก iterableสั้น:

L=[*T]
*L,=T

ไวยากรณ์ที่คล้ายกันใช้ได้กับสิ่งอันดับ:

T=*L,

ซึ่งเหมือนกับขยาย iterable ขยาย แต่ด้วยเครื่องหมายดอกจันและเครื่องหมายจุลภาคในด้านอื่น ๆ

กำลังเข้าร่วมรายการ / สิ่งอันดับ

การคลายไฟล์จะสั้นกว่าการต่อข้อมูลเล็กน้อยหากคุณต้องการผนวก list / tuple ไว้ทั้งสองด้าน:

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

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

การพิมพ์เนื้อหาของหลายรายการ

นี่ไม่ได้ จำกัด อยู่printแต่แน่นอนว่าระยะทางส่วนใหญ่จะมาจาก ตอนนี้ PEP448 อนุญาตให้เปิดหลายกล่องได้เช่น:

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

การอัปเดตรายการพจนานุกรมหลายรายการ

สิ่งนี้อาจจะไม่เกิดขึ้นบ่อยนัก แต่สามารถใช้ไวยากรณ์เพื่อบันทึกการอัพเดตพจนานุกรมได้หากคุณกำลังปรับปรุงอย่างน้อยสามรายการ:

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

dict.updateนี้โดยทั่วไปจะขัดแย้งกับความจำเป็นในการใด ๆ


6
มันดูแย่กว่า Perl แต่มันใช้งานได้ ...
Mega Man

20

เปลี่ยนimport *เป็นimport*


หากคุณไม่เคยได้ยินให้import*บันทึกตัวอักษร!

from math import*

มีความยาวมากกว่า 1 อักขระimport math as mและคุณจะลบอินสแตนซ์ทั้งหมดของm.

แม้แต่การใช้เพียงครั้งเดียวก็ช่วยได้!


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

ถ้าคุณค่าของฉันไม่มีประโยชน์:

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

หรือ

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

8
คุณสามารถทำให้ตัวอย่างที่สองเป็นfor i in[0]*x:s+=input()บันทึกพื้นที่อื่น นอกจากนี้คุณสามารถลบช่องว่างระหว่าง exec และเครื่องหมายคำพูดแรกที่จะได้รับexec's+=input();'*x
Justin Peel

บรรทัดที่สองไม่ควรเป็น:for i in[0]*x:s+=input()
micsthepick

Dupe (ใหม่ แต่มีผู้
โหวต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.