Gibt es einen Unterschied zwischen p
und puts
in Ruby?
Gibt es einen Unterschied zwischen p
und puts
in Ruby?
Antworten:
p foo
Druck , foo.inspect
gefolgt von einem Newline, dh sie den Wert drucken inspect
statt to_s
, die für das Debuggen von mehr geeignet ist (weil man zB den Unterschied zwischen sagen 1
, "1"
und "2\b1"
, was man kann nicht beim Drucken ohne inspect
).
p
auch den Wert des Objekts zurückgibt, dies puts
jedoch nicht. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
to_s
ist die Standard- To -String-Methode in Ruby. inspect
. Wie gesagt, ist eine alternative to-string-Methode, die eine Ausgabe erzeugt, die besser zum Debuggen geeignet ist. Nach Abschluss des Debuggens sollten Sie natürlich Ihre Debugging-Anweisungen entfernen (oder für ernstere Projekte sollten Sie wahrscheinlich ein Protokollierungsframework verwenden und p oder Puts überhaupt nicht zum Debuggen verwenden). Die Tatsache, dass p
das Objekt zurückgegeben wird, scheint in den meisten Situationen irrelevant (und ich glaube, ich habe diese Antwort gegeben, bevor dies der Fall war). Der Unterschied in der Ausgabe ist der Hauptunterschied (und war früher der einzige).
Es ist auch wichtig zu beachten, dass puts
"reagiert" auf eine Klasse, die to_s
definiert hat, p
nicht. Zum Beispiel:
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>
Dies folgt direkt aus dem .inspect
Aufruf, ist aber in der Praxis nicht offensichtlich.
p foo
ist das gleiche wie puts foo.inspect
puts
kehrt aber zurück nil
, anstatt foo
wie p
.
puts foo.inspect; foo
(-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
. Viele positive Stimmen machen dies NICHT zu einer guten Antwort!
Zusätzlich zu den obigen Antworten gibt es einen subtilen Unterschied in der Konsolenausgabe - nämlich das Vorhandensein / Fehlen von Anführungszeichen / Anführungszeichen -, der nützlich sein kann:
p "+++++"
>> "+++++"
puts "====="
>> =====
Ich finde dies nützlich, wenn Sie einen einfachen Fortschrittsbalken erstellen möchten, indem Sie den nahen Verwandten print verwenden :
array = [lots of objects to be processed]
array.size
>> 20
Dies gibt den 100% Fortschrittsbalken:
puts "*" * array.size
>> ********************
Und dies fügt bei jeder Iteration ein inkrementelles * hinzu:
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
Schreibt die angegebenen Objekte in ios. Schreibt eine neue Zeile nach einer, die noch nicht mit einer neuen Zeile endet. Gibt null zurück .
Der Stream muss zum Schreiben geöffnet werden. Wenn mit einem Array- Argument aufgerufen , wird jedes Element in eine neue Zeile geschrieben. Jedes Objekt, das keine Zeichenfolge oder kein Array ist, wird durch Aufrufen seiner
to_s
Methode konvertiert . Wenn ohne Argumente aufgerufen, wird eine einzelne neue Zeile ausgegeben.
Lass es uns auf irb versuchen
# 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
Schreiben Sie für jedes Objekt direkt,obj.inspect
gefolgt von einem Zeilenumbruch in die Standardausgabe des Programms.
in 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
Diese 2 sind gleich:
p "Hello World"
puts "Hello World".inspect
( inspect bietet eine wörtlichere Ansicht des Objekts als die Methode to_s. )
(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Dies kann einen der Hauptunterschiede veranschaulichen, der darin besteht, p
den Wert dessen zurückzugeben, was an ihn übergeben wird, wobei as puts
zurückgegeben wird 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']
Benchmark-Shows puts
sind langsamer
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)