p vs mette in Ruby


270

C'è qualche differenza tra pe putsin Ruby?

Risposte:


334

p foostampe foo.inspectseguite da una nuova riga, ovvero stampa il valore di inspectinvece di to_s, che è più adatto per il debug (perché puoi ad esempio dire la differenza tra 1, "1"e "2\b1", che non puoi quando stampi senza inspect).


7
Sì, p (e put) sono entrambi nel modulo Kernel, quindi puoi vedere i dettagli qui: ruby-doc.org/core/classes/Kernel.html#M005961
mikej

17
Si noti che prestituisce anche il valore dell'oggetto, mentre putsnon lo fa. 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng,

2
Ottimo riassunto fornito da Gareth Rees nel suo post intitolato "Ruby p vs put vs print" .
alexanderjsingleton,

Un po 'mi sembra che questo mi lasci con un buco di coniglio di domande. Cosa ispeziona? Cosa c'è? Perché voglio controllare il testo stampato anziché una variabile? Qual è più standard per il mondo della programmazione, a causa della tua menzione di debug, p o put? Tutte le "p" dovrebbero essere sostituite da "put" al completamento del debug ?? Vedo, in un commento sopra, che p restituisce un oggetto, che è una differenza enorme. Non sono sicuro che questa risposta sia completa se menziona solo una piccola differenza che porterà a domande più grandi che comunque rispondono alla domanda originale.

1
@AaronLoften to_sè il metodo standard a stringa in Ruby. inspect. come ho detto, è un metodo alternativo alla stringa, che produce un output più adatto per il debug. Al termine del debug è necessario rimuovere ovviamente le dichiarazioni di debug (o per progetti più seri è consigliabile utilizzare un framework di registrazione e non utilizzare p o put per il debug). Il fatto che prestituisca l'oggetto sembra irrilevante nella maggior parte delle situazioni (e credo di aver dato questa risposta prima che questo fosse il caso). La differenza nell'output è la differenza principale (ed era l'unica).
sepp2k,

54

È anche importante notare che puts"reagisce" a una classe che ha to_sdefinito, pno. Per esempio:

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>

Ciò deriva direttamente dalla .inspectchiamata, ma non è ovvio in pratica.


37

p foo equivale a puts foo.inspect


4
ma putsritorna nil, invece di foocome fa p.
Ribamar

10
È sbagliato. È lo stesso diputs foo.inspect; foo
Eric Duminil l'

Questo dimostra che siete la risposta non è corretta: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . Molti voti NON ne fanno una buona risposta!
lacostenycoder,

3

Oltre alle risposte di cui sopra, esiste una sottile differenza nell'output della console - vale a dire la presenza / assenza di virgole / virgolette invertite - che può essere utile:

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

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

Lo trovo utile se vuoi creare una semplice barra di avanzamento, usando il loro parente stretto, stampa :

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

Questo dà la barra di avanzamento del 100%:

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

E questo aggiunge un * incrementale su ogni iterazione:

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

A partire dal documento ruby-2.4.1

mette

puts(obj, ...) → nil

Scrive gli oggetti dati su iOS. Scrive una nuova riga dopo quella che non termina già con una sequenza di nuova riga. Restituisce zero .

Lo stream deve essere aperto per la scrittura. Se chiamato con un argomento array , scrive ogni elemento su una nuova riga. Ogni dato oggetto che non è una stringa o un array verrà convertito chiamando il suo to_s metodo. Se chiamato senza argomenti, genera una nuova riga.

proviamo su 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
Per ogni oggetto, scrive direttamente obj.inspectseguito da una nuova riga nell'output standard del programma.

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

0

Questi 2 sono uguali:

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

( inspect offre una visione più letterale dell'oggetto rispetto al metodo to_s )


sembrano uguali, ma NON lo sono. Da provare:(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder,

0

Questo può illustrare una delle differenze chiave che è che prestituisce il valore di ciò che gli viene passato, dove come putsritorna 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']

Gli spettacoli di benchmark sono putspiù lenti

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.