p vs setzt Ruby ein

270

Gibt es einen Unterschied zwischen pund putsin Ruby?

Collimarco
quelle

Antworten:

333

p fooDruck , foo.inspectgefolgt von einem Newline, dh sie den Wert drucken inspectstatt 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).

sepp2k
quelle
7
Ja, p (und Puts) befinden sich beide im Kernel-Modul, sodass Sie die Details hier sehen können: ruby-doc.org/core/classes/Kernel.html#M005961
mikej
17
Beachten Sie, dass dies pauch den Wert des Objekts zurückgibt, dies putsjedoch nicht. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng
2
Tolle Zusammenfassung von Gareth Rees in seinem Beitrag "Ruby p vs Puts vs Print" .
Alexander
Ich habe das Gefühl, dass ich ein Hasenloch voller Fragen habe. Was inspizieren? Was ist to_s? Warum möchte ich gedruckten Text anstelle einer Variablen überprüfen? Was ist aufgrund Ihrer Erwähnung von Debugging, P oder Puts mehr Standard für die Welt der Programmierung? Sollten alle "p" nach Abschluss des Debuggens durch "Puts" ersetzt werden? Ich sehe in einem obigen Kommentar, dass p ein Objekt zurückgibt, was einen großen Unterschied darstellt. Ich bin mir nicht sicher, ob diese Antwort vollständig ist, wenn nur ein kleiner Unterschied erwähnt wird, der zu größeren Fragen führt, die die ursprüngliche Frage immer noch beantworten.
1
@AaronLoften to_sist 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 pdas 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).
sepp2k
54

Es ist auch wichtig zu beachten, dass puts"reagiert" auf eine Klasse, die to_sdefiniert hat, pnicht. 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 .inspectAufruf, ist aber in der Praxis nicht offensichtlich.

ezpz
quelle
37

p foo ist das gleiche wie puts foo.inspect

August Lilleaas
quelle
4
putskehrt aber zurück nil, anstatt foowie p.
Ribamar
10
Das ist falsch. Es ist das gleiche wieputs foo.inspect; foo
Eric Duminil
Dies beweist, dass Ihre Antwort falsch ist : (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Viele positive Stimmen machen dies NICHT zu einer guten Antwort!
Lacostenycoder
3

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
>> ******
Jonathan_W
quelle
2

Aus Ruby-2.4.1-Dokument

setzt

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

p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...] p() → nil
Schreiben Sie für jedes Objekt direkt, obj.inspectgefolgt 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
Fangxing
quelle
0

Diese 2 sind gleich:

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

( inspect bietet eine wörtlichere Ansicht des Objekts als die Methode to_s. )

Apadana
quelle
sie scheinen gleich zu sein, aber sie sind NICHT. Probieren Sie es aus:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
Lacostenycoder
0

Dies kann einen der Hauptunterschiede veranschaulichen, der darin besteht, pden Wert dessen zurückzugeben, was an ihn übergeben wird, wobei as putszurü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 putssind 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)
Lacostenycoder
quelle