Có sự khác biệt nào giữa p
và puts
trong Ruby không?
Có sự khác biệt nào giữa p
và puts
trong Ruby không?
Câu trả lời:
p foo
các bản in được foo.inspect
theo sau bởi một dòng mới, tức là nó in giá trị inspect
thay 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"
và "2\b1"
, khi bạn không thể in mà không in inspect
).
p
cũng trả về giá trị của đối tượng, trong khi puts
không. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
là 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ế p
trả 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).
Cũng cần lưu ý rằng puts
"phản ứng" với một lớp đã to_s
được định nghĩa, p
thì 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ừ .inspect
cuộc gọi, nhưng không rõ ràng trong thực tế.
p foo
giống như puts foo.inspect
puts
trả lại nil
, thay vì foo
như vậy p
.
puts foo.inspect; foo
(-> {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!
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
>> ******
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(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil
Đối với mỗi đối tượng, ghi trực tiếpobj.inspect
theo 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
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 )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Điều này có thể minh họa một trong những khác biệt chính đó là p
trả về giá trị của những gì được truyền cho nó, nơi puts
trả 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 puts
chậ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)