Python: วิธีที่ไม่มีการแปลงเป็นสตริงที่ว่างเปล่า?


156

วิธีการทำตามสำนวนที่เป็นไปได้มากที่สุด

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

อัปเดต:ฉันกำลังรวมข้อเสนอแนะของ Tryptich ในการใช้ str (s) ซึ่งทำให้รูทีนนี้ทำงานได้สำหรับประเภทอื่น ๆ นอกเหนือจากสตริง ฉันประทับใจมากกับคำแนะนำแลมบ์ดาของ Vinay Sajip แต่ฉันต้องการให้โค้ดของฉันค่อนข้างเรียบง่าย

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)

7
ฉันชอบไวยากรณ์ดั้งเดิมของคุณ ฉันคิดว่ามันค่อนข้างชัดเจนและอ่านง่าย
GuiSim

1
@GuiSim: ฉันอาจจะลำเอียง แต่คำตอบของฉันอ่านเกือบจะเหมือนประโยคภาษาอังกฤษปกติ ...
SilentGhost

1
"ถ้า s เป็น None ให้ส่งคืนสตริงว่างมิฉะนั้นส่งคืน [string of] s" รหัสจากคำถามจะอ่านเหมือนประโยคภาษาอังกฤษทั่วไปเช่นกัน

a) ถ้าสตริงsมาจากการค้นหา dict โดยที่ไม่พบคีย์ให้ใช้dict.get(key, '')
smci

b) หากคุณต้องการเพียงแค่การแปลงสตริงสำหรับการจัดรูปแบบผลลัพธ์ (เช่นสำหรับการพิมพ์) คุณสามารถทำรูปแบบ '... {}' ได้โดยตรง (dict.get (1)) ``
smci

คำตอบ:


94

หากคุณต้องการให้ฟังก์ชันของคุณทำงานเหมือนในstr()ตัว แต่ส่งคืนสตริงว่างเมื่ออาร์กิวเมนต์ไม่มีให้ทำดังนี้

def xstr(s):
    if s is None:
        return ''
    return str(s)

ฉันรักษาอย่างอื่น แต่ขอบคุณสำหรับเคล็ดลับ str เพื่อให้สามารถจัดการได้หลายประเภท ดี!
มาร์คแฮร์ริสัน

12
หรือเพียงxstr = lambda s: '' if s is None else str(s)
Michael Mior

2
ฉันชอบพิมพ์if not s:แทนif s is None
guneysus

6
@guneysus พวกเขาจะไม่เหมือนกัน: แต่not False == True False is None == False
ลินน์

ขอบคุณ @Lynn คุณพูดถูก ฉันตระหนักถึงความผิดของฉัน แต่ฉันรู้ว่า (หรือสมมติ) sเสมอใน STR / Unicode Noneพิมพ์หรือ ใช่Falseเป็นค่า แต่ฉันชอบวิธีนี้ที่จะช่วยประหยัดแป้นพิมพ์และตาของฉัน;)
guneysus

143
def xstr(s):
    return '' if s is None else str(s)

3
ไวยากรณ์นี้ถูกนำเสนอใน 2.5; return s is not None and s or ''สำหรับรุ่นก่อนหน้าของงูใหญ่คุณสามารถใช้
Ben Blank

8
ฉันหันไปรอบ ๆ เพื่อเน้นกรณี commen เพิ่มเติมได้ที่: การกลับมา s ถ้า s ไม่ได้ไม่มีที่อื่น ""
เบอร์

5
@Ber: ฉันจะเก็บไว้ตามที่เป็นอยู่เพื่อหลีกเลี่ยงการลบสองครั้ง
Nikhil Chelliah

8
นี่เป็นตัวอย่างที่ดีของความ.. and .. or ..ล้มเหลวและเหตุผลว่าทำไมจึงเป็นที่ต้องการ s is not None and s or ''มีสองข้อบกพร่องที่ลึกซึ้งในกำลัง

1
return '' if not s else str(s)
อิกบัล

110

น่าจะเป็นที่สั้นที่สุด str(s or '')

เนื่องจากไม่มีเป็นเท็จและ "x หรือ y" ส่งคืน y ถ้า x เป็นเท็จ ดูผู้ประกอบการบูลีนสำหรับคำอธิบายโดยละเอียด มันสั้น แต่ไม่ชัดเจนมาก


1
มันเยี่ยมมากขอบคุณ! ไม่เคยคิดว่าจะใช้orวิธีนี้
user25064

15
วิธีนี้ใช้ไม่ได้ถ้าsเป็น 0, เท็จ, หรือค่าเท็จ ๆ
wisbucky

4
นั่นไม่ได้กล่าวถึงในข้อกำหนดของ op ดังนั้นฉันไม่เห็นประเด็นของคุณที่นี่
dorvak

2
@dorvak สหกรณ์ค่อนข้างชัดเจนเกี่ยวกับความต้องการที่ส่งออกควรจะIFF'' s is Noneอินพุตอื่นทั้งหมดควรส่งคืนs(หรือstr(s)ในคำขอที่แก้ไข)
StvnW

2
@fortea: มันไม่ทำงาน ถ้าsเป็นNoneเช่นนั้นผลลัพธ์ของxstr()ควรเป็นสตริงที่ว่างเปล่า แต่str(None)ให้สตริง"None"ซึ่งเป็นสิ่งที่ถูกส่งคืน (เนื่องจากสตริง"None"นั้นไม่ใช่ค่าที่ผิดพลาด
Dreamlax

97

หากคุณรู้ว่าค่าจะเป็นสตริงหรือไม่ก็:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''

1
โดยไกลมากที่สุด pythonic ใช้ความจริงที่ว่าหลามปฏิบัติกับไม่มีรายการที่ว่างเปล่าสตริงว่าง, 0, ฯลฯ เป็นเท็จ ใช้ความจริงที่ว่าคำสั่ง or ส่งคืนองค์ประกอบแรกที่เป็นจริงหรือองค์ประกอบสุดท้ายที่กำหนดให้กับหรือ (หรือกลุ่มของ ors) นอกจากนี้ยังใช้ฟังก์ชั่นแลมบ์ดา ฉันจะให้ +10 แต่เห็นได้ชัดว่ามันจะไม่ให้ฉัน
Matt

11
นี้จะแปลง 0 และเท็จ (และสิ่งอื่นใดที่ประเมินเป็นเท็จเมื่อส่งผ่านไปยังบูล))
Arkady

9
ฉันไม่คิดว่ามันจะ "ไพเราะที่สุด" มันเป็นสำนวนสามัญในภาษาอื่นและฉันไม่คิดว่ามันผิดที่จะใช้ใน Python แต่เป็นการแสดงออกตามเงื่อนไขที่ถูกนำมาใช้อย่างแม่นยำเพื่อหลีกเลี่ยงเทคนิคเช่นนี้
Roberto Bonvallet

2
ทำให้นี้[], {}ฯลฯ ให้ผลเช่นเดียวกับการNoneที่ไม่ได้ต้องการ xstr(False)โดยเฉพาะอย่างยิ่งควรจะแทน"False" ""การใช้ลูกแกะในทางที่ผิดนั้นเป็นตัวอย่างที่ไม่ดีให้ใช้def xstr(s): return s or ""ir ที่คุณต้องการเก็บไว้ในบรรทัดเดียว

5
โปรดทราบว่าฉันได้รับคำตอบเมื่อเริ่มต้นด้วย "ถ้าคุณรู้ว่าค่าจะเป็นสตริงหรือไม่มี" เสมอ
Vinay Sajip

59

return s or '' จะทำงานได้ดีสำหรับปัญหาที่คุณระบุไว้!


4
น่าสังเกตว่าสิ่งนี้จะให้ผลลัพธ์ที่แตกต่างกันเมื่อ s เป็นเท็จหรือ 0 (ซึ่งไม่ใช่คำถามสตริงเดิม แต่เป็นคำถามที่ได้รับการอัปเดต)
Oddthinking

@ คิดs = Falseหรือs = 0น่าจะเป็นกรณีขอบในการใช้งานและสามารถบรรเทาได้อย่างง่ายดายโดยการเขียนมันเป็นreturn str(s or '')
Willem van Ketwich

@WillemvanKetwich: นั่นเป็นปัญหาเดียวกันทั้งหมด: s (เท็จ) ควรส่งคืน 'เท็จ' ไม่ใช่ '' s (0) ควรส่งคืน '0' ไม่ใช่ '' ในทำนองเดียวกันสำหรับวัตถุที่กำหนด __bool__ หรือ __nonzero__
Oddthinking

@ คิดทบทวนฉันเห็นประเด็นของคุณ ไม่ว่าในกรณีใด ๆ หากมีการใช้เฉพาะสำหรับวัตถุสตริงเช่นในคำถามของ OP มันจะไม่เป็นปัญหา
Willem van Ketwich

@WillemvanKetwich: ดูคำถามที่ปรับปรุงแล้วและข้อแม้ในความคิดเห็นของฉัน - ได้รับการคุ้มครอง
Oddthinking

14
def xstr(s):
   return s or ""

4
ผลตอบแทนนี้''สำหรับ0, [], {}, Falseและเท็จเหมือนค่าซึ่งไม่ได้เป็นสิ่งที่โปสเตอร์ถามหา
StvnW

1
เพียงแค่ใส่ str ([... ]) รอบ s: def xstr(s): return str(s) or ""
Federico Simonetta

8

วิธีการทำงาน (หนึ่งซับ)

xstr = lambda s: '' if s is None else s

1
"def xstr (s): การกลับมา '' ถ้า s คือไม่มีอื่น s" บนซับเกินไปหลามไม่เป็นที่เข้มงวดกับช่องว่างหลังจากทั้งหมด
SilentGhost

2
มันไม่ใช่ของจริงแบบเขียนเดี่ยวเขียนแค่หนึ่งบรรทัดg
Dario

1
ในความหมายใดมันไม่ได้เป็น onliner จริง? ตรวจสอบล่ามของคุณ - ไม่ใช่ข้อผิดพลาดทางไวยากรณ์ สำหรับทุกเจตนาและวัตถุประสงค์มันเป็นวิธีที่แท้จริงกว่าแลมบ์ดา ^ ^ ^
SilentGhost

2
PEP 8 สปีชีส์ที่คุณควรใช้ def แทนที่จะกำหนดแลมบ์ดาให้กับตัวแปร ข้อได้เปรียบที่แท้จริงเพียงอย่างเดียวของแลมบ์ดาคือคุณสามารถเขียนเป็นส่วนหนึ่งของการแสดงออก (ส่งผ่านไปยังฟังก์ชันอื่นเช่น) และข้อดีนั้นจะหายไปในรหัสเช่นนี้ ฉันเคยทำเช่นนี้จนกระทั่งฉันสังเกตเห็นว่า def สามารถเขียนในบรรทัดเดียวแล้ว PEP 8 แสดงให้ฉันเห็นวิธีที่จะไป ทำตามเทพหลามเสมอ
Guy

8

สายการบินเดียวที่เรียบร้อยในการทำอาคารนี้กับคำตอบอื่น ๆ :

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

หรือแม้แต่เพียงแค่:

s = (a or '') + (b or '')

ทำไมพูดถึง(lambda v: v or '')?
Tvde1

ทำไมจะไม่ล่ะ? 2 เคล็ดลับสำหรับราคา 1! 😀
Willem van Ketwich

1
โปรดทราบว่าFalseและรายการว่างจะถูกเปลี่ยนเป็น ''
Nik O'Lai

กันสำหรับ0ฯลฯ
Walter Tross

6
def xstr(s):
    return {None:''}.get(s, s)

ฉันคิดว่ามันค่อนข้างไพเราะ - แล้วอันนี้: "xstr = lambda s: {None: ''}. get (s, s)" - ลดสิ่งทั้งปวงให้เป็นหนึ่งซับ
Juergen

14
ช้าโดยไม่จำเป็น (การสร้างและการค้นหาแบบพิเศษเพิ่ม) และอ่านยากขึ้น ค่อนข้างไพเราะ
Triptych

คุณถูก. มันค่อนข้างจะเพรียวลม แต่ก็หลีกเลี่ยงการกระโดดตามเงื่อนไขใน python bytecode
tobidope

4
การเรียกใช้ฟังก์ชัน get () หมายถึงการกระโดดแบบมีเงื่อนไขเพิ่มเติมอย่างน้อยหนึ่งครั้ง
Triptych

1
ฉัน wouln't getจะสามารถที่จะพูดในสิ่งที่ควรทำโดยไม่ทราบว่าคำถามหรือเงยหน้าขึ้นมอง
Dario

5

ฉันใช้ฟังก์ชั่นสูงสุด:

max(None, '')  #Returns blank
max("Hello",'') #Returns Hello

ทำงานเหมือนเครื่องราง;) เพียงแค่ใส่สตริงของคุณในพารามิเตอร์แรกของฟังก์ชั่น


5
สิ่งนี้ใช้งานได้เพราะ 'str'> 'NoneType' และเป็นเฉพาะ CPython จากคู่มือ : "วัตถุประเภทต่าง ๆ ยกเว้นหมายเลขเรียงตามชื่อประเภท" นอกจากนี้สิ่งนี้จะไม่ทำงานใน Python 3000 เนื่องจากการเปรียบเทียบระหว่างประเภทไม่ได้รับอนุญาตอีกต่อไป (TypeError: ประเภทที่ไม่สามารถจัดลำดับได้: str ()> NoneType ()) ดูPython เปรียบเทียบสตริงและ int อย่างไร
plok

เป็นการดีที่จะรู้ว่าขอบคุณดังนั้นจึงไม่ใช่ความคิดที่ดีที่จะก้าวไปข้างหน้าด้วยรหัสที่เข้ากันได้กับ python 3.x
radtek


2

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

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)

1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))

5
นี่จะส่งคืนสตริงว่างเปล่าสำหรับค่าเท็จทั้งหมดซึ่งไม่ใช่สิ่งที่ผู้ขอโปสเตอร์ร้องขอ
Triptych

1

เราสามารถหลีกเลี่ยงการแคสติ้งประเภทในสถานการณ์ที่อธิบายไว้ด้านล่าง

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

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

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

ตัวอย่างข้างต้นจะทำงานอย่างถูกต้อง สถานการณ์ดังกล่าวเป็นเรื่องธรรมดามากเมื่อค่าถูกดึงมาจาก URL, JSON หรือ XML หรือแม้กระทั่งค่าที่ต้องการประเภทการคัดเลือกนักแสดงเพิ่มเติมสำหรับการจัดการใด ๆ


0

ใช้การประเมินไฟฟ้าลัดวงจร:

s = a or '' + b or ''

เนื่องจาก + เป็นการดำเนินการที่ไม่ดีกับสตริงจึงควรใช้รูปแบบสตริง:

s = "%s%s" % (a or '', b or '')

2
สิ่งนี้จะแปลง 'a' เป็นสตริงว่างสำหรับค่า false เหมือนทั้งหมดไม่ใช่แค่ None ตัวอย่างเช่น tuples ว่างเปล่ารายการและ dicts จะแปลงเป็นสตริงว่างซึ่งไม่ใช่สิ่งที่ OP ระบุ
Triptych

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

+1 สำหรับฉันเพราะนี่คือสิ่งที่ฉันต้องการในกรณีของฉัน: แลมบ์ดาหรือฟังก์ชั่นเพื่อแทนที่โอเปอเรเตอร์เดียว ( or) ดูเหมือนว่าราคาแพงเกินไปสำหรับฉัน ... ฉันไม่มีกรณีที่มีค่าแอบแฝงอื่น ๆ นอกเหนือจากความคิดเห็นเกี่ยวกับ+ผู้ประกอบการซึ่งอาจขึ้นอยู่กับสถานการณ์ที่เฉพาะเจาะจงและอาจต้องทำการเปรียบเทียบคำตอบนี้ไม่สมควรได้รับ -1
urban

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