【问题标题】:p vs puts in Rubyp vs 放入 Ruby
【发布时间】:2009-08-10 14:44:50
【问题描述】:

Ruby 中的pputs 有什么区别吗?

【问题讨论】:

    标签: ruby


    【解决方案1】:

    p foo 打印foo.inspect 后跟一个换行符,即它打印inspect 的值而不是to_s,这更适合调试(因为您可以例如区分1、@ 987654328@ 和 "2\b1",如果没有 inspect,则无法打印)。

    【讨论】:

    • 是的,p(和 puts)都在内核模块中,所以你可以在这里查看详细信息:ruby-doc.org/core/classes/Kernel.html#M005961
    • 请注意,p 也返回对象的值,而 puts 不返回。 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
    • Gareth Rees 在题为 "Ruby p vs puts vs print" 的帖子中提供了精彩的总结。
    • 有点感觉这给我留下了很多问题。检查什么? to_s 是什么?为什么我要检查打印文本而不是变量?由于您提到了调试,p 或 puts,哪个是编程世界的标准?调试完成后是否应该将所有“p”替换为“puts”?我在上面的评论中看到 p 返回一个对象,这是一个巨大的差异。我不确定这个答案是否完整,如果它只提到一个小的差异会导致更大的问题仍然可以回答原始问题。
    • @AaronLoften to_s 是 Ruby 中的标准 to-string 方法。 inspect。正如我所说,它是一种替代字符串方法,它产生更适合调试的输出。完成调试后,您显然应该删除调试语句(或者对于更严重的项目,您可能应该使用日志框架,而根本不使用 p 或 puts 进行调试)。 p 返回对象的事实在大多数情况下似乎无关紧要(我相信在这种情况下我已经给出了这个答案)。输出的差异是主要差异(并且曾经是唯一的差异)。
    【解决方案2】:

    同样重要的是要注意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 fooputs foo.inspect 相同

      【讨论】:

      • puts 返回 nil,而不是 foo,就像 p 一样。
      • 错了。同puts foo.inspect; foo
      • 这证明你的答案不正确:(-&gt; {p "Hello World"}.call) == (-&gt; {puts "Hello World".inspect}.call ) 。许多赞成票并不能使这成为一个好的答案!
      【解决方案4】:

      来自ruby-2.4.1 document

      看跌

      puts(obj, ...) → nil

      将给定对象写入 ios。在任何之后写一个换行符 尚未以换行序列结束。 返回零

      必须打开流进行写入。如果使用 数组 调用 参数,将每个元素写在新行上。每个给定的对象 不是字符串或数组的将通过调用其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
      

      【讨论】:

        【解决方案5】:

        除了上述答案之外,控制台输出还有一个细微的差别——即是否存在反引号/引号——这可能很有用:

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

        【讨论】:

          【解决方案6】:

          这两个是相等的:

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

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

          【讨论】:

          • 它们看起来相等,但实际上并非如此。试试看:(-&gt;{p "Hello World"}.call) == (-&gt; {puts "Hello World".inspect}.call )
          【解决方案7】:

          这可能说明了一个关键区别,即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)
          

          【讨论】:

            【解决方案8】:

            p 方法将打印更广泛的可调试消息,其中puts 将美化消息代码。

            例如看下面的代码行:

            msg = "hey, Use \#{ to interpolate expressions"
            puts msg #clean msg
            p msg #shows \ with #
            

            输出将是

            hey, Use #{ to interpolate expressions
            "hey, Use \#{ to interpolate expressions"
            

            see output pic for more clarity

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-08-30
              • 2021-12-23
              • 2018-10-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多