Ruby:参数与变量

时间:2016-11-20 02:01:17

标签: ruby

所以我开始学习ruby,我发现我们可以在方法中使用默认值,这看起来类似于只有实例变量,除了减少代码行之外,这是否有任何重要性或好处?

//这

def order_food(price, size="large", quantity = 8)
    if quantity == 1
      extra = "salad"
    else
      extra = "Burgers"
    end
    puts "#{quantity} #{size} #{extra}, coming right up!"
  end

//到此

def order_food(price)
    size = "large"
    quantity = 8
    if quantity == 1
      extra = "salad"
    else
      extra = "Burgers"
    end
    puts "#{quantity} #{size} #{extra}, coming right up!"
  end

5 个答案:

答案 0 :(得分:4)

在深思熟虑的同时,我意识到这提供了一个非常大的好处是灵活性和可读性。 例如,我可以传递像

这样的参数
order_food(2, "small", 90)

这允许我覆盖默认值,这比在

时更改变量内容更好
order_food(9, "extraLarge")

获取我设置的默认数量

答案 1 :(得分:3)

它与实例变量不同。实例变量具有类实例的范围,并使用@符号声明。

例如:

class MyClass

  def initialise
    @my_instance_variable = 'hello world'
  end

  def method_one
    puts "I have access to the instance variable and it is #{@my_instance_variable}"
  end
end

你所展示的只是方法范围的局部变量声明,但是一个是为你的方法定义一个参数而另一个是没有。

def order_food(price, size="large", quantity = 8)

相当于:

def order_food(price)
    size = "large"
    quantity = 8

虽然大小和数量都是变量,并且两者都只有order_food方法的范围,但第一种方法是将它们声明为方法可以接受的参数,因此可以这样调用:

order_food(5, 'small', 2)

而在第二个例子中,这些不能由被叫者设定 - 它们固定在“大”的位置。和8。

没有必要使用默认值声明方法参数,但通过这样做,被调用者不需要提供它们,而是使用默认值。所以对于方法声明:

def order_food(price, size="large", quantity = 8)

您可以拨打以下电话:

order_food price: 10, quantity: 2 #will use default size with value 'large'
order_food price: 5, size: 'small' #will use default quantity of 8

答案 2 :(得分:2)

首先,变量是局部变量而不是实例变量。实例变量属于类的实例,并以@var_name表示法标注,而局部变量属于范围(非常简单,即do ... end所包围的任何内容。更详细here并且仅使用变量名称(my_var = "some_value")进行标注。

这取决于您使用该方法的内容。如果您希望能够传递参数quantitysize,那么您应该使用第一个参数。如果你尝试传递超过1个参数,第二个将给你和ArgumentError。第一个将设置quantity = 8size = "large"的值,如果它们没有被传递,但如果它们被传递,它将使用传递的值。

如果您希望能够调用方法并将大小和数量设置为参数,如果未传递它们,请使用size = "large"quantity = 8作为默认值,使用第一种方法:

order_food "9.00" #=> "8 large burgers, coming right up!"
order_food "9.00", "small", 1 #=> "1 small salad, coming right up!"

第二种方法不允许您传递其他两个参数中的任何一个,并且它们将始终设置为quantity = 8size = "large"。这有其好处,因为有时您不希望变量可以通过参数进行更改。所以使用第二种方法:

order_food "9.00" #=> "8 large burgers, coming right up!"
order_food "9.00", "small", 1 #=> ArgumentError: wrong number of arguments (given 3, expected 1)

答案 3 :(得分:1)

这是一个重新编写的代码版本,它更像Ruby:

def order_food(price, size: :large, quantity: 1)
  extras =
    case (quantity)
    when 1
      "salad"
    else
      "Burgers"
    end

  "#{quantity} #{size} #{extra}, coming right up!"
end

puts order_food(2, :small, 8)

在方法中进行显示(puts)通常会给方法带来太多责任。从构成问题中分离显示问题。也许您想将其写入文件,或将其嵌入HTML中。方法中的puts限制了您的选择。

如果你想拥有一些本质上有些随意的数量,也可以利用关键字参数。这允许您跳过一个并使用另一个而不需要重新指定默认值的代码。

答案 4 :(得分:0)

实际上有4种将参数传递给函数的常用方法。 你的第一个例子是最常见的例子,但是我害怕你做了一个坏榜样。你的数量总是8,所以if是多余的,也没有使用参数价格所以也是多余的 这与以下

相同
    def order_food price
      "8 large Burgers, coming right up!"
    end

但我认为这不是你的目的。

所以,它会是这样的 第一种方法

def order_food1(size, quantity, price)
  extra = quantity == 1 ? :salad : :Burgers
  cost  = quantity * price
  "#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end

+快(见基准)

+每个人都使用它并在一个glace中理解它

- 您必须知道参数及其定义的顺序,您需要阅读不太常用的API方法

- 您必须提供所有参数

下一步:使用带默认值的可选参数

def order_food2(size = "large", quantity = 1, price = 4)
  extra = quantity == 1 ? :salad : :Burgers
  cost  = quantity * price
  "#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end

+也广泛使用

+如果参数是默认参数,则无需使用参数

- 你仍然需要知道参数的顺序和含义,如果使用了最后一个,你需要它们

下一步:使用哈希作为参数

def order_food3(opts = {})
  opts = {size: :large, quantity: 1, price: 4}.merge!(opts)
  extra = opts[:quantity] == 1 ? :salad : :Burgers
  cost  = opts[:quantity] * opts[:price]
  "#{opts[:quantity]} #{opts[:size]} #{extra}, coming right up! Thats is #{cost} dollar please"
end

- 少用,你的方法自我有点难以阅读

- 慢点

+无需知道您不需要的参数,也无需知道订单

+使用该方法更具可读性

下一步:上一种方法的简化版

def order_food4(size: :large, quantity: 1, price: 4)
  extra = :quantity == 1 ? :salad : :Burgers
  cost  = quantity * price
  "#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end

- 慢点

+方法本身及其使用更具可读性

哪一个更好?取决于个人品味和情况。 我使用了所有这些,据我所知,设计指南中没有任何内容可以说是其中之一。 在实践中,你甚至可以将其中一些组合起来。 很少更改的参数最好给出默认值,反之亦然。 多次调用的方法(例如递归方法)可以从更快且更少消耗内存的方法1中受益。 在我看来,可读性对于Ruby脚本来说是最重要的,所以如果有很多参数和可行的使用方法3或4。

使用和基准的一些例子..

puts order_food1("large", 3, 4)
puts order_food2("large", 3, 4)
puts order_food3(size: "large", quantity: 3, price: 4)
puts order_food3
puts order_food4(size: "large", quantity: 3, price: 4)
puts order_food4

# 3 large Burgers, coming right up! Thats is 12 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 1 large salad, coming right up! Thats is 4 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 1 large Burgers, coming right up! Thats is 4 dollar please

require 'benchmark'

Benchmark.bmbm do |x|
  x.report("order_food1    ")   { 10000.times { order_food1("large", 3, 12) }}
  x.report("order_food2    ")   { 10000.times { order_food2("large", 3, 12) }} # all parameters given
  x.report("order_food2_def")   { 10000.times { order_food2 }} # using default parameters
  x.report("order_food3    ")   { 10000.times { order_food3(size: "large", quantity: 3, price: 12) }} # all parameters given
  x.report("order_food3 def")   { 10000.times { order_food3 }} # using default parameters
  x.report("order_food4    ")   { 10000.times { order_food3(size: "large", quantity: 3, price: 12) }} # all parameters given
  x.report("order_food4 def")   { 10000.times { order_food3 }} # using default parameters
end

#                       user     system      total        real
# order_food1       0.015000   0.000000   0.015000 (  0.010420)
# order_food2       0.000000   0.000000   0.000000 (  0.010675)
# order_food2_def   0.016000   0.000000   0.016000 (  0.011007)
# order_food3       0.015000   0.000000   0.015000 (  0.020182)
# order_food3 def   0.016000   0.000000   0.016000 (  0.016954)
# order_food4       0.015000   0.000000   0.015000 (  0.020256)
# order_food4 def   0.000000   0.000000   0.000000 (  0.016968)