Rubyのpとput


回答:


334

p foofoo.inspect後に改行が表示されます。つまり、のinspect代わりにの値が出力されます。to_sこれは、デバッグにより適しています(たとえば1"1"との違い"2\b1"を確認できるため、なしで印刷する場合は区別できませんinspect)。


7
うん、p(とputs)はどちらもKernelモジュールにあるので、ここで詳細を確認できます。ruby
doc.org

17
pはオブジェクトの値も返しますが、返さないことに注意してくださいputs1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng、

2
Gareth Reesが投稿した"Ruby p vs puts vs print"というタイトルのすばらしい要約。
alexanderjsingleton 2016

ちょっとこれは私にウサギの穴の質問を残しているような気がします。何を検査しますか?to_sは?なぜ変数の代わりに印刷されたテキストを検査したいのですか?デバッグ、p、またはputについて言及しているため、プログラミングの世界でより標準的なものはどれですか。デバッグが完了したら、すべての「p」を「puts」に置き換えますか?上記のコメントで、pがオブジェクトを返すことがわかります。これは大きな違いです。この答えが完全であるかどうかわからないのですが、元の質問に答えるような大きな質問につながる小さな違いについてのみ言及している場合は、

1
@AaronLoften to_sは、Rubyの標準のto-stringメソッドです。inspect。言ったように、これは文字列に代わる方法で、デバッグにより適した出力を生成します。デバッグが完了したら、デバッグステートメントを明らかに削除する必要があります(または、より深刻なプロジェクトでは、おそらくロギングフレームワークを使用し、pまたはputsをデバッグに使用しないでください)。pオブジェクトを返すという事実は、ほとんどの状況では無関係であるように思われます(これが事実になる前に私がこの答えを出したと私は信じています)。出力の違いが主な違いです(かつては唯一の違いでした)。
sepp2k 2016年

54

定義putsしたクラスに「反応する」とは反応しないことに注意することも重要です。例えば:to_sp

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>

これは.inspect呼び出しから直接続きますが、実際には明らかではありません。


37

p foo と同じです puts foo.inspect


4
puts返すのnilではなく、 fooを返しますp
ribamar

10
それは間違っている。それは同じですputs foo.inspect; foo
Eric Duminil

これは、答えが間違っていることを示しています:(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) 。多くの賛成投票では、これは良い答えにはなりません!
lacostenycoder

3

上記の回答に加えて、コンソール出力には微妙な違いがあります。つまり、反転カンマ/引用符の有無です。

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

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

親戚のprintを使用して単純なプログレスバーを作成したい場合、これは便利です。

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

これにより、100%の進行状況バーが表示されます。

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

そして、これは各反復で増分*を追加します:

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

ルビー2.4.1文書

置く

puts(obj, ...) → nil

指定されたオブジェクトをiosに書き込みます。改行シーケンスでまだ終了していない改行を書き込みますnilを返します

書き込み用にストリームを開く必要があります。配列 引数を指定して呼び出された場合、各要素を新しい行に書き込みます。文字列または配列ではない指定された各オブジェクトは、そのto_s メソッドを呼び出すことによって変換されます。引数なしで呼び出された場合、単一の改行を出力します。

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

p

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
オブジェクトごとobj.inspectに、プログラムの標準出力に改行を続けて直接書き込みます。

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

これら2つは等しい:

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

inspectは、to_sメソッドと比較して、オブジェクトのよりリテラルなビューを提供します)


それらは同等に見えますが、違います。試してみる:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

これpは、渡されたものの値を返すという主な違いの1つを示している可能性がありputsます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']

ベンチマーク番組putsは遅い

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.