p vs đặt trong Ruby


270

Có sự khác biệt nào giữa pputstrong Ruby không?

Câu trả lời:


334

p foocác bản in được foo.inspecttheo sau bởi một dòng mới, tức là nó in giá trị inspectthay vì to_s, phù hợp hơn để gỡ lỗi (vì bạn có thể nói sự khác biệt giữa 1, "1""2\b1", khi bạn không thể in mà không in inspect).


7
Yep, p (và đặt) đều nằm trong mô-đun Kernel để bạn có thể xem chi tiết tại đây: ruby-doc.org/core/groupes/Kernel.html#M005961
mikej

17
Lưu ý rằng pcũng trả về giá trị của đối tượng, trong khi putskhông. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng

2
Tóm tắt tuyệt vời được cung cấp bởi Gareth Rees trong bài đăng của mình có tên "Ruby p vs put vs print" .
alexanderjsingleton

Kinda cảm thấy như thế này để lại cho tôi một lỗ thỏ câu hỏi. Kiểm tra cái gì? Có chuyện gì vậy? Tại sao tôi muốn kiểm tra văn bản in thay vì một biến? Đó là tiêu chuẩn hơn cho thế giới lập trình, do bạn đề cập đến gỡ lỗi, p hoặc đặt? Có nên thay thế tất cả "p" bằng "put" khi hoàn thành quá trình sửa lỗi không ?? Tôi thấy, trong một nhận xét trên, p trả về một đối tượng, đó là một sự khác biệt rất lớn. Tôi không chắc câu trả lời này có đầy đủ hay không nếu nó chỉ đề cập đến một sự khác biệt nhỏ sẽ dẫn đến những câu hỏi lớn hơn mà vẫn trả lời được câu hỏi ban đầu.

1
@AaronLoften to_slà phương thức chuỗi tiêu chuẩn trong Ruby. inspect. như tôi đã nói, là một phương thức thay thế chuỗi, tạo ra một đầu ra phù hợp hơn để gỡ lỗi. Sau khi hoàn thành việc gỡ lỗi, rõ ràng bạn nên xóa các câu lệnh gỡ lỗi của mình (hoặc đối với các dự án nghiêm trọng hơn, có lẽ bạn nên sử dụng khung ghi nhật ký và không sử dụng p hoặc đặt để gỡ lỗi). Thực tế ptrả về đối tượng dường như không liên quan trong hầu hết các tình huống (và tôi tin rằng tôi đã đưa ra câu trả lời này trước khi đây là trường hợp). Sự khác biệt trong đầu ra là sự khác biệt chính (và được sử dụng là duy nhất).
sepp2k

54

Cũng cần lưu ý rằng puts"phản ứng" với một lớp đã to_sđược định nghĩa, pthì không. Ví dụ:

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>

Điều này diễn ra trực tiếp từ .inspectcuộc gọi, nhưng không rõ ràng trong thực tế.


37

p foo giống như puts foo.inspect


4
nhưng putstrả lại nil, thay vì foonhư vậy p.
ribamar

10
Sai rồi. Nó giống nhưputs foo.inspect; foo
Eric Duminil 8/12/2016

Điều này chứng tỏ rằng câu trả lời của bạn không chính xác : (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Nhiều upvote KHÔNG làm cho điều này một câu trả lời tốt!
lacostenycoder

3

Ngoài các câu trả lời ở trên, có một sự khác biệt tinh tế trong đầu ra của bàn điều khiển - cụ thể là sự hiện diện / vắng mặt của dấu phẩy / dấu ngoặc kép ngược - có thể hữu ích:

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

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

Tôi thấy điều này hữu ích nếu bạn muốn tạo một thanh tiến trình đơn giản, sử dụng họ hàng gần của họ, in :

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

Điều này mang lại cho thanh tiến trình 100%:

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

Và điều này thêm một số gia * trên mỗi lần lặp:

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

Từ tài liệu ruby-2.4.1

đặt

puts(obj, ...) → nil

Viết (các) đối tượng đã cho vào ios. Viết một dòng mới sau bất kỳ dòng nào chưa kết thúc bằng một chuỗi dòng mới. Trả về con số không .

Các luồng phải được mở để viết. Nếu được gọi với một đối số mảng , hãy viết từng phần tử trên một dòng mới. Mỗi đối tượng đã cho không phải là một chuỗi hoặc mảng sẽ được chuyển đổi bằng cách gọi to_s phương thức của nó . Nếu được gọi mà không có đối số, xuất ra một dòng mới.

hãy thử nó trên 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
Đối với mỗi đối tượng, ghi trực tiếp obj.inspecttheo dòng mới đến đầu ra tiêu chuẩn của chương trình.

trong 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 cái này bằng nhau:

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

( kiểm tra cho một cái nhìn chân thực hơn về đối tượng so với phương thức to_s )


họ có vẻ như nhau, nhưng họ KHÔNG. Hãy thử:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

Điều này có thể minh họa một trong những khác biệt chính đó là ptrả về giá trị của những gì được truyền cho nó, nơi putstrả về 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']

Điểm chuẩn cho thấy putschậm hơn

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.