p vs放入Ruby


Answers:


334

p foo打印foo.inspect跟着一个新行,即它打印的值inspect代替to_s,这是更适合的调试(因为可以例如告诉之间的差异1"1""2\b1",这些你不打印不能时inspect)。


7
是的,p(和puts)都在内核模块中,因此您可以在此处查看详细信息:ruby-doc.org/core/classes/Kernel.html#M005961
mikej,2009年

17
注意,它p也返回对象的值,而不返回puts1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
达伦·郑

2
Gareth Rees在其题为“ Ruby p vs puts vs print”的文章中提供了精彩的摘要。
alexanderjsingleton

有点像这样让我感到困惑。什么检查?什么?为什么要检查打印的文本而不是变量?由于您提到调试,p或puts,哪个编程世界更标准?调试完成后,是否应将所有“ p”替换为“ puts”?我在上面的评论中看到p返回一个对象,这是一个巨大的差异。我不确定如果仅提及一个小的差异会导致这个较大的问题,仍然会回答原始问题,那么这个答案是否完整。

1
@AaronLoften to_s是Ruby中的标准字符串转换方法。inspect。如我所说,是字符串方法的替代方法,它产生的输出更适合调试。调试完成后,您显然应该删除调试语句(或者,对于更严重的项目,您可能应该使用日志记录框架,而根本不使用p或puts进行调试)。p在大多数情况下,返回对象的事实似乎无关紧要(而且我相信在这种情况之前,我已经给出了这个答案)。输出的差异是主要差异(过去是唯一的差异)。
sepp2k 16-10-4

54

同样重要的是要注意puts对已to_s定义的类的“反应” p不会。例如:

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调用,但是在实践中并不明显。



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

ruby-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

这两个相等:

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

(与to_s方法相比,inspect提供了更直观的对象视图)


它们看起来相等,但不是。试试看:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

这可能说明了关键区别之一,那就是p返回传递给它的值,其中as为putsreturn 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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.