Python: cara paling idiomatik untuk mengonversi None ke string kosong?

156

Apa cara paling idiomatis untuk melakukan hal berikut?

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

s = xstr(a) + xstr(b)

pembaruan: Saya memasukkan saran Tryptich untuk menggunakan str (s), yang membuat rutin ini berfungsi untuk jenis lain selain string. Saya sangat terkesan dengan saran lambda Vinay Sajip, tetapi saya ingin menjaga kode saya relatif sederhana.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)
Mark Harrison
sumber
7
Saya suka sintaksis asli Anda. Saya pikir itu sudah cukup jelas dan mudah dibaca.
GuiSim
1
@GuiSim: Aku mungkin bias, tapi jawaban saya membaca hampir seperti kalimat bahasa Inggris yang normal ...
SilentGhost
1
"Jika s Tidak ada, maka kembalikan string kosong; jika tidak, kembalikan [string] s." Kode dari pertanyaan tersebut berbunyi seperti kalimat bahasa Inggris yang normal juga.
a) Jika string sberasal dari pencarian dict di mana kunci tidak ditemukan, kemudian gunakandict.get(key, '')
smci
b) Jika Anda hanya menginginkan konversi string ini untuk format output (misalnya untuk cetak), maka Anda dapat langsung melakukan format '... {}'. (dict.get (1)) `
smci

Jawaban:

94

Jika Anda benar-benar ingin fungsi Anda berperilaku seperti str()built-in, tetapi mengembalikan string kosong ketika argumennya adalah None, lakukan ini:

def xstr(s):
    if s is None:
        return ''
    return str(s)
Triptych
sumber
Saya menyimpan yang lain, tapi terima kasih atas tipnya sehingga banyak jenis dapat ditangani. bagus!
Mark Harrison
11
Atau sederhananyaxstr = lambda s: '' if s is None else str(s)
Michael Mior
2
Saya suka mengetik dan if not s:bukannyaif s is None
guneysus
6
@guneysus Mereka tidak sama: not False == Truetetapi False is None == False.
Lynn
Terima kasih @ Lynn kamu benar. Saya menyadari kesalahan saya. Tapi saya tahu (atau berasumsi) sselalu dalam str / unicode type atau None. Ya, Falseadalah nilai tetapi saya lebih suka cara ini yang menyelamatkan keyboard dan mata saya;)
guneysus
143
def xstr(s):
    return '' if s is None else str(s)
SilentGhost
sumber
3
Sintaks ini diperkenalkan pada 2.5; untuk versi Python sebelumnya, Anda bisa menggunakannya return s is not None and s or ''.
Ben Blank
8
Aku akan memutarnya untuk menekankan kasus yang lebih commen: kembali s jika s tidak ada yang lain ""
Ber
5
@ Bir: Saya akan menyimpannya apa adanya, untuk menghindari negatif ganda.
Nikhil Chelliah
8
Ini adalah contoh yang baik tentang bagaimana .. and .. or ..gagal dan mengapa jika yang lain lebih disukai. Ada dua bug halus di s is not None and s or ''.
1
return '' if not s else str(s)
Iqbal
108

Mungkin yang terpendek adalah str(s or '')

Karena Tidak Ada yang Salah, dan "x atau y" mengembalikan y jika x salah. Lihat Operator Boolean untuk penjelasan terperinci. Ini pendek, tetapi tidak terlalu eksplisit.

dorvak
sumber
1
ini sangat bagus, terima kasih! Tidak pernah terpikir untuk menggunakan orcara ini
user25064
15
Ini tidak berfungsi jika s0, False, atau nilai salah apa pun
wisbucky
4
Ya, itu tidak disebutkan dalam persyaratan op, jadi saya tidak mengerti maksud Anda di sini.
dorvak
2
@dorvak OP cukup eksplisit tentang persyaratan bahwa output harus ''iff s is None. Semua input lain harus dikembalikan s(atau str(s)dalam permintaan yang direvisi).
StvnW
2
@fortea: itu tidak akan berhasil. Jika sadalah None, hasil dari xstr()harus string kosong, tetapi str(None)memberikan string "None", yang adalah apa yang dikembalikan (karena string "None"bukan nilai falsy.
dreamlax
97

Jika Anda tahu bahwa nilainya akan selalu berupa string atau Tidak ada:

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) # -> ''
Vinay Sajip
sumber
1
sejauh ini yang paling pythonic. Menggunakan fakta bahwa python memperlakukan None, daftar kosong, string kosong, 0, dll sebagai false. Juga menggunakan fakta bahwa pernyataan atau mengembalikan elemen pertama yang benar atau elemen terakhir yang diberikan kepada atau (atau grup ors). Ini juga menggunakan fungsi lambda. Saya akan memberi Anda +10 tetapi jelas itu tidak akan membiarkan saya.
Matt
11
Ini akan mengonversi 0 dan False (dan apa pun yang mengevaluasi ke False ketika diteruskan ke bool ())
Arkady
9
Saya tidak berpikir itu "sejauh ini yang paling pythonic". Ini adalah idiom umum dalam bahasa lain, dan saya rasa tidak salah untuk menggunakannya dalam Python, tetapi ekspresi kondisional yang diperkenalkan dengan tepat untuk menghindari trik seperti ini.
Roberto Bonvallet
2
Ini membuat [],, {}dll. Memberikan hasil yang sama seperti None, yang tidak diinginkan. xstr(False), khususnya, seharusnya "False"bukan "". Menyalahgunakan lambdas sebagai contoh yang buruk, gunakan def xstr(s): return s or ""ir yang ingin Anda pertahankan dalam satu jalur.
5
Perhatikan bahwa saya memenuhi syarat jawaban saya di awal dengan "Jika Anda tahu bahwa nilainya akan selalu berupa string atau Tidak Ada".
Vinay Sajip
59

return s or '' akan bekerja dengan baik untuk masalah yang Anda nyatakan!

Alex Martelli
sumber
4
Perlu dicatat bahwa ini akan memberikan hasil yang berbeda ketika s adalah False atau 0 (yang bukan pertanyaan string asli, tetapi yang diperbarui.)
Oddthinking
@Oddikir s = Falseatau s = 0kemungkinan besar akan menjadi kasus tepi dalam penggunaannya dan dapat dengan mudah dikurangi dengan menuliskannya sebagaireturn str(s or '')
Willem van Ketwich
@ WillemvanKetwich: Itu memiliki masalah yang persis sama: s (Salah) harus mengembalikan 'Salah', bukan ''. s (0) harus mengembalikan '0', bukan ''. Demikian juga untuk objek yang mendefinisikan __bool__ atau __nonzero__.
Penghinaan
@Oddikir saya mengerti maksud Anda. Dalam kasus apa pun, jika digunakan secara eksklusif untuk objek string seperti dalam pertanyaan OP, itu seharusnya tidak menjadi masalah.
Willem van Ketwich
@ WillemvanKetwich: Lihatlah pertanyaan yang diperbarui dan peringatan dalam komentar saya - ini telah dibahas,
Oddthinking
14
def xstr(s):
   return s or ""
Krystian Cybulski
sumber
4
Kembali ini ''untuk 0, [], {}, Falsedan false-seperti nilai-nilai, yang tidak apa poster minta.
StvnW
1
hanya menempatkan str ([...]) di sekitar s: def xstr(s): return str(s) or ""
Federico Simonetta
8

Cara fungsional (satu-liner)

xstr = lambda s: '' if s is None else s
Dario
sumber
1
"def xstr (s): return '' if s is None else s" juga on-liner, python tidak seketat spasi putih
SilentGhost
2
Ini bukan liner sungguhan, hanya ditulis dalam satu baris g
Dario
1
dalam arti apa itu bukan onliner nyata? periksa penerjemah Anda - ini bukan kesalahan sintaksis. untuk semua maksud dan tujuan itu cara nyata daripada lambda ^ _ ^
SilentGhost
2
Spesies PEP 8 yang harus Anda gunakan def alih-alih menugaskan lambda ke variabel. Satu-satunya keuntungan nyata dari lambda adalah Anda dapat menulis sebagai bagian dari ekspresi (beralih ke fungsi lain misalnya) dan keuntungan itu hilang dalam kode seperti ini. Saya biasa melakukan ini juga, sampai saya perhatikan bahwa def dapat ditulis dalam satu baris, dan kemudian PEP 8 menunjukkan kepada saya cara untuk pergi. SELALU mengikuti dewa-dewa python.
Guy
8

Satu lapis yang rapi untuk mengerjakan bangunan ini pada beberapa jawaban lain:

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

atau bahkan hanya:

s = (a or '') + (b or '')
Willem van Ketwich
sumber
Kenapa bahkan disebutkan (lambda v: v or '')?
Tvde1
Kenapa tidak? 2 tips untuk harga 1! 😀
Willem van Ketwich
1
Perlu diketahui bahwa Falsedan daftar kosong juga akan berubah menjadi ''.
Nik O'Lai
sama untuk 0, dll.
Walter Tross
6
def xstr(s):
    return {None:''}.get(s, s)
tobidope
sumber
Saya pikir, ini agak pythonic - bagaimana dengan yang ini: "xstr = lambda s: {None: ''}. Get (s, s)" - mereduksi semuanya menjadi satu baris.
Juergen
14
Tidak perlu lambat (konstruksi dict ekstra dan pencarian), dan lebih sulit untuk dibaca. Cukup unpythonic.
Triptych
Kamu benar. Ini agak umum tetapi menghindari lompatan kondisional dengan bytecode python.
tobidope
4
Panggilan fungsi get () menyiratkan setidaknya satu lompatan kondisional tambahan.
Triptych
1
Saya tidak akan bisa mengatakan apa yang harus dilakukan tanpa mengetahui pertanyaan atau melihat ke atas get.
Dario
5

Saya menggunakan fungsi maks:

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

Bekerja seperti pesona;) Masukkan saja string Anda ke dalam parameter pertama dari fungsi.

radtek
sumber
5
Ini berfungsi karena 'str'> 'NoneType', dan spesifik untuk CPython. Dari manual : "Objek dengan tipe berbeda kecuali nomor diurutkan berdasarkan nama tipenya". Juga, ini tidak akan berfungsi di Python 3000, karena perbandingan antar-jenis tidak lagi diizinkan (TypeError: tipe yang tidak dapat dipesan: str ()> NoneType ()). Lihat Bagaimana Python membandingkan string dan int?
plok
Baik untuk mengetahui terima kasih, jadi bukan ide yang baik untuk terus maju dengan kode yang kompatibel dengan python 3.x.
radtek
4

Variasi di atas jika Anda harus kompatibel dengan Python 2.4

xstr = lambda s: s is not None and s or ''
Peter Ericson
sumber
2

Jika ini tentang memformat string, Anda dapat melakukan hal berikut:

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)
maciek
sumber
1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
Phillc
sumber
5
Ini akan mengembalikan string kosong untuk semua nilai false-like, yang bukan yang diminta poster.
Triptych
1

Kami selalu dapat menghindari tipe casting dalam skenario yang dijelaskan di bawah ini.

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

Dalam contoh di atas dalam kasus nilai pelanggan variabel adalah Tidak ada yang selanjutnya mendapatkan casting saat ditugaskan ke 'nama'. Perbandingan dalam klausa 'jika' akan selalu gagal.

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)

Contoh di atas akan bekerja dengan baik. Skenario seperti itu sangat umum ketika nilai diambil dari URL, JSON atau XML atau bahkan nilai perlu pengecoran tipe lebih lanjut untuk manipulasi apa pun.

Pralhad Narsinh Sonar
sumber
0

Gunakan evaluasi hubung singkat:

s = a or '' + b or ''

Karena + bukan operasi yang sangat baik pada string, lebih baik gunakan format string:

s = "%s%s" % (a or '', b or '')
Sharjeel
sumber
2
Ini juga akan mengonversi 'a' menjadi string kosong untuk semua nilai mirip-palsu, bukan hanya Tidak Ada. Misalnya, tupel kosong, daftar, dan dikt akan dikonversi menjadi string kosong, yang bukan apa yang ditentukan OP.
Triptych
+adalah operator yang sangat baik untuk dua string. Saat Anda mencoba menggunakannya untuk bergabung dengan lusinan Anda mengalami kesulitan. Untuk dua, mungkin akan lebih cepat daripada opsi lain; Bagaimanapun, itu dalam kebisingan.
kquinn
1 untuk saya karena inilah yang saya butuhkan dalam kasus saya: lambda atau fungsi untuk menggantikan satu operator ( or) tampaknya sedikit berlebihan bagi saya ... Saya tidak punya kasus nilai-nilai palsu lainnya - baik str atau Tidak ada. Selain dari komentar pada +operator, yang mungkin tergantung pada skenario tertentu dan mungkin perlu benchmarking, jawaban ini tidak layak -1
perkotaan
-3

Gunakan string F jika Anda menggunakan python v3.7

xstr = F"{s}"
pengguna781486
sumber
1
Ini salah dan mengembalikan string 'None'jika sada None.
Lawrence