p 대 루비를 넣습니다


답변:


334

p foo인쇄는 foo.inspect, 개행 다음은 값 출력, 즉 inspect대신에 to_s(당신이 예 사이의 차이를 말할 수 있기 때문에 디버깅에 더 적합 1, "1"그리고 "2\b1"당신이없이 인쇄 할 수 없을 때하는 inspect).


7
: 여기에 세부 사항을 볼 수 있도록 네, P (및 풋)는 커널 모듈에서 모두 ruby-doc.org/core/classes/Kernel.html#M005961
mikej

17
참고 p하면서 또한, 개체의 값을 반환 puts하지 않습니다. 1.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

이런 느낌이 들기 때문에 토끼 구멍이 생길 것입니다. 무엇을 검사합니까? 무슨 일이야? 변수 대신 인쇄 된 텍스트를 검사하고 싶은 이유는 무엇입니까? 디버깅, p 또는 put에 대한 언급으로 인해 프로그래밍 세계에서 더 표준적인 것은 무엇입니까? 디버깅이 완료되면 모든 "p"를 "puts"로 바꾸어야합니까 ?? 위의 주석에서 p가 객체를 반환한다는 것을 알았습니다. 이는 큰 차이입니다. 원래의 질문에 여전히 응답하는 더 큰 질문으로 이어질 작은 차이 만 언급하면이 답변이 완전한지 확실하지 않습니다.

1
@AaronLoften to_s은 Ruby의 표준 문자열 방식입니다. inspect. 내가 말했듯이 대체 문자열 방법으로 디버깅에 더 적합한 출력을 생성합니다. 디버깅이 완료되면 분명히 디버깅 문을 제거해야합니다 (또는 더 심각한 프로젝트의 경우 로깅 프레임 워크를 사용하고 p 또는 디버깅을 전혀하지 않아야합니다). p객체 를 반환하는 사실 은 대부분의 상황에서 관련이없는 것 같습니다 (그리고 이것이 사실이기 전에이 답변을했다고 생각합니다). 출력의 차이는 주요한 차이이며, 유일한 차이였습니다.
sepp2k

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반환합니다 . nilfoop
ribamar

10
그건 틀렸어요. 이 같은입니다puts foo.inspect; foo
에릭 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(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

( inspectto_s 메소드 와 비교하여 객체를보다 문자 그대로 보여줍니다 )


그들은 똑같아 보이지만 그렇지 않습니다. 시도 :(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

이것은 즉 주요 차이점 중 하나 설명 할 수 있습니다 p곳으로, 반환 그것을 전달되는 값 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.