p vs วางใน Ruby


คำตอบ:


334

p fooพิมพ์foo.inspectตามด้วยการขึ้นบรรทัดใหม่เช่นจะพิมพ์ค่าของinspectแทนto_sซึ่งจะเหมาะสำหรับการแก้จุดบกพร่อง (เพราะคุณสามารถเช่นบอกความแตกต่างระหว่าง1, "1"และ"2\b1"ซึ่งคุณไม่สามารถเมื่อพิมพ์โดยไม่ต้องinspect)


7
ใช่, p (และPut
mikej

17
โปรดทราบว่าpยังส่งคืนค่าของวัตถุในขณะที่putsไม่ 1.9.3p125 :002 > (p "foo").class "foo" => String 1.9.3p125 :003 > (puts "foo").class foo => NilClass
Darren Cheng

2
สรุปมากโดยแกเร็ ธ ทัลบอทในโพสต์ของเขาที่ชื่อ"ทับทิมพี VS ทำให้ VS พิมพ์"
alexanderjsingleton

ความรู้สึกแบบนี้ทำให้ฉันมีหลุมคำถาม ตรวจสอบอะไร to_s อะไร เหตุใดฉันจึงต้องการตรวจสอบข้อความที่พิมพ์แทนที่จะเป็นตัวแปร มาตรฐานของโลกแห่งการเขียนโปรแกรมอะไรมากขึ้นเนื่องจากคุณพูดถึงการดีบั๊ก, p หรือทำให้? "p" ทั้งหมดควรถูกแทนที่ด้วย "Put" เมื่อเสร็จสิ้นการดีบั๊กหรือไม่? ฉันเห็นในความคิดเห็นข้างต้นว่า p ส่งคืนวัตถุซึ่งแตกต่างกันมาก ฉันไม่แน่ใจว่าคำตอบนี้เสร็จสมบูรณ์หรือไม่หากมันกล่าวถึงความแตกต่างเพียงเล็กน้อยที่จะนำไปสู่คำถามที่ใหญ่กว่าซึ่งยังคงตอบคำถามเดิมอยู่

1
@AaronLoften to_sเป็นวิธีมาตรฐานของสตริงใน Ruby inspect. อย่างที่ฉันบอกว่าเป็นวิธีการทางเลือกสตริงซึ่งผลิตผลลัพธ์ที่เหมาะสมสำหรับการแก้จุดบกพร่อง เมื่อเสร็จสิ้นการดีบักคุณควรลบข้อความสั่งการดีบัก (หรือสำหรับโครงการที่จริงจังกว่านี้คุณควรใช้กรอบการบันทึกและไม่ใช้ p หรือทำให้การดีบักเลย) ความจริงที่ว่าpวัตถุที่ส่งคืนดูเหมือนไม่เกี่ยวข้องในสถานการณ์ส่วนใหญ่ (และฉันเชื่อว่าฉันให้คำตอบนี้ก่อนหน้านี้เป็นกรณี) ความแตกต่างในผลลัพธ์เป็นความแตกต่างหลัก (และเคยเป็นเพียงคนเดียว)
sepp2k

54

นอกจากนี้ยังเป็นสิ่งสำคัญที่จะต้องทราบว่าputs"ตอบสนอง" กับชั้นเรียนที่to_sกำหนดไว้pไม่ได้ ตัวอย่างเช่น:

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>

สิ่งนี้ตามมาโดยตรงจากการ.inspectโทร แต่ไม่ชัดเจนในทางปฏิบัติ


37

p foo เป็นเช่นเดียวกับ puts foo.inspect


4
แต่putsคืนค่าnilแทนที่จะ fooเป็นเช่นpนั้น
ribamar

10
มันผิด มันเป็นเช่นเดียวกับputs foo.inspect; foo
Eric Duminil

นี่เป็นการพิสูจน์ว่าคำตอบของคุณไม่ถูกต้อง: (-> {p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call ) . upvotes จำนวนมากไม่ได้ทำให้คำตอบนี้ดี!
lacostenycoder

3

นอกเหนือจากคำตอบข้างต้นแล้วยังมีความแตกต่างเล็กน้อยในเอาต์พุตคอนโซล - นั่นคือการมี / ไม่มีเครื่องหมายจุลภาค / อัญประกาศคว่ำ - ที่มีประโยชน์:

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

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

ฉันพบว่ามีประโยชน์หากคุณต้องการสร้างแถบความคืบหน้าอย่างง่ายโดยใช้ญาติสนิทของพวกเขา พิมพ์ :

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

สิ่งนี้จะทำให้แถบความคืบหน้า 100%:

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

และสิ่งนี้จะเพิ่ม * ซ้ำในแต่ละการวนซ้ำ:

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

จากเอกสารทับทิม 2.4.1

ทำให้

puts(obj, ...) → nil

เขียนวัตถุที่กำหนดไปยัง ios เขียนขึ้นบรรทัดใหม่หลังจากที่ไม่ได้ลงท้ายด้วยลำดับการขึ้นบรรทัดใหม่ ผลตอบแทนที่ศูนย์

ต้องเปิดสตรีมเพื่อการเขียน หากถูกเรียกพร้อมกับอาเรย์ อาร์กิวเมนต์ให้เขียนแต่ละองค์ประกอบในบรรทัดใหม่ แต่ละวัตถุที่กำหนดที่ไม่ใช่สตริงหรืออาร์เรย์จะถูกแปลงโดยการเรียกto_s ใช้เมธอด หากถูกเรียกโดยไม่มีอาร์กิวเมนต์เอาต์พุตจะขึ้นบรรทัดใหม่เดียว

ลองดูที่ 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
สำหรับแต่ละวัตถุเขียนโดยตรงobj.inspectตามด้วยบรรทัดใหม่ไปยังเอาต์พุตมาตรฐานของโปรแกรม

ใน 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 เหล่านี้เท่ากัน:

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

( ตรวจสอบให้มุมมองที่แท้จริงของวัตถุมากกว่าวิธีto_s )


พวกเขาดูเหมือนเท่ากัน แต่พวกเขาไม่ใช่ ลองทำดูสิ(->{p "Hello World"}.call) == (-> {puts "Hello World".inspect}.call )
lacostenycoder

0

ซึ่งอาจแสดงให้เห็นถึงหนึ่งของความแตกต่างที่สำคัญซึ่งเป็นที่pผลตอบแทนที่คุ้มค่าของสิ่งที่ผ่านไปที่เป็นผลตอบแทนputsnil

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']

การเปรียบเทียบสมรรถนะputsช้าลง

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.