p vs menempatkan di Ruby


270

Apakah ada perbedaan antara pdan putsdi Ruby?

Jawaban:


334

p foocetakan foo.inspectdiikuti oleh baris baru, yaitu mencetak nilai inspectalih - alih to_s, yang lebih cocok untuk debugging (karena Anda dapat misalnya membedakan antara 1, "1"dan "2\b1", yang Anda tidak dapat saat mencetak tanpa inspect).


7
Yap, p (dan put) keduanya dalam modul Kernel sehingga Anda dapat melihat detailnya di sini: ruby-doc.org/core/classes/Kernel.html#M005961
mikej

17
Perhatikan bahwa pjuga mengembalikan nilai objek, sementara putstidak. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng

2
Ringkasan hebat diberikan oleh Gareth Rees dalam postingannya yang berjudul "Ruby p vs puts vs print" .
alexanderjsingleton

Agak merasa seperti ini membuat saya dengan lubang pertanyaan kelinci. Apa yang diperiksa? Whats to_s? Mengapa saya ingin memeriksa teks cetak dan bukan variabel? Mana yang lebih standar untuk dunia pemrograman, karena Anda menyebutkan debugging, p atau menempatkan? Haruskah semua "p" diganti dengan "menempatkan" setelah selesai debugging ?? Saya melihat, dalam komentar di atas, bahwa p mengembalikan objek, yang merupakan perbedaan besar. Saya tidak yakin apakah jawaban ini selesai jika hanya menyebutkan perbedaan kecil yang akan mengarah pada pertanyaan yang lebih besar yang masih menjawab pertanyaan aslinya.

1
@AaronLoften to_sadalah metode to-string standar di Ruby. inspect. seperti yang saya katakan, adalah metode alternatif ke-string, yang menghasilkan output yang lebih cocok untuk debugging. Setelah menyelesaikan debugging Anda harus menghapus pernyataan debugging Anda (atau untuk proyek yang lebih serius Anda mungkin harus menggunakan kerangka kerja logging dan tidak menggunakan p atau menempatkan untuk debugging sama sekali). Fakta yang pmengembalikan objek tampaknya tidak relevan dalam kebanyakan situasi (dan saya percaya saya memberikan jawaban ini sebelum ini terjadi). Perbedaan dalam output adalah perbedaan utama (dan dulunya satu-satunya).
sepp2k

54

Penting juga untuk dicatat bahwa puts"bereaksi" ke kelas yang telah to_sdidefinisikan, ptidak. Sebagai contoh:

class T
   def initialize(i)
      @i = i
   end
   def to_s
      @i.to_s
   end
end

t = T.new 42
puts t   => 42
p t      => #<T:0xb7ecc8b0 @i=42>

Ini mengikuti langsung dari .inspectpanggilan, tetapi tidak jelas dalam praktiknya.


37

p foo sama dengan puts foo.inspect


4
tetapi putskembali nil, bukan fooseperti halnya p.
ribamar

10
Itu salah. Itu sama denganputs foo.inspect; foo
Eric Duminil

Ini membuktikan bahwa jawaban yang sedang tidak benar: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Banyak upvotes TIDAK membuat ini jawaban yang bagus!
lacostenycoder

3

Selain jawaban di atas, ada perbedaan halus dalam output konsol - yaitu ada / tidak adanya tanda koma / tanda kutip - yang dapat berguna:

p "+++++"
>> "+++++"

puts "====="
>> =====

Saya menemukan ini berguna jika Anda ingin membuat progress bar sederhana, menggunakan kerabat dekatnya, cetak :

array = [lots of objects to be processed]
array.size
>> 20

Ini memberikan bilah kemajuan 100%:

puts "*" * array.size
>> ********************

Dan ini menambahkan * inkremental pada setiap iterasi:

array.each do |obj|
   print "*"
   obj.some_long_executing_process
end

# This increments nicely to give the dev some indication of progress / time until completion
>> ******

2

Dari dokumen ruby-2.4.1

menempatkan

puts(obj, ...) → nil

Menulis objek yang diberikan ke ios. Menulis baris baru setelah yang belum berakhir dengan urutan baris baru. Pengembalian nihil .

Aliran harus dibuka untuk ditulis. Jika dipanggil dengan argumen array , tulis setiap elemen pada baris baru. Setiap objek yang diberikan bukan string atau array akan dikonversi dengan memanggil to_s metodenya. Jika dipanggil tanpa argumen, menghasilkan satu baris baru.

ayo coba di irb

# always newline in the end 
>> puts # no arguments

=> nil # return nil and writes a newline
>> puts "sss\nsss\n" # newline in string
sss
sss
=> nil
>> puts "sss\nsss" # no newline in string
sss
sss
=> nil

# for multiple arguments and array
>> puts "a", "b"
a
b
=> nil
>> puts "a", "b", ["c", "d"]
a
b
c
d
=> nil

hal

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
Untuk setiap objek, tulis langsung obj.inspectdiikuti oleh baris baru ke output standar program.

di irb

# no arguments
>> p
=> nil # return nil, writes nothing
# one arguments
>> p "sss\nsss\n" 
"sss\nsss\n"
=> "aaa\naaa\n"
# multiple arguments and array
>> p "a", "b"
"a"
"b"
=> ["a", "b"] # return a array
>> p "a", "b", ["c", "d"]
"a"
"b"
["c", "d"]
=> ["a", "b", ["c", "d"]] # return a nested array

0

Ini 2 adalah sama:

p "Hello World"  
puts "Hello World".inspect

( inspect memberikan pandangan objek yang lebih literal dibandingkan dengan metode to_s )


mereka tampak sama, tetapi TIDAK. Cobalah:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

Ini dapat menggambarkan salah satu perbedaan utama yaitu pmengembalikan nilai dari apa yang diteruskan ke sana, di mana sebagai putspengembalian nil.

def foo_puts
  arr = ['foo', 'bar']
  puts arr
end

def foo_p
  arr = ['foo', 'bar']
  p arr
end

a = foo_puts
=>nil
a
=>nil

b = foo_p
=>['foo', 'bar']
b
['foo', 'bar']

Pertunjukan benchmark putslebih lambat

require 'benchmark'
str = [*'a'..'z']
str = str*100
res = Benchmark.bm do |x|
  x.report(:a) { 10.times {p str} }
  x.report(:b) { 10.times {puts str} }
end
puts "#{"\n"*10}"
puts res

0.010000   0.000000   0.010000 (  0.047310)
0.140000   0.090000   0.230000 (  0.318393)
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.