在创建对象时将哈希作为初始值传递

时间:2017-12-08 01:41:05

标签: ruby

我正在使用实例方法创建一个Temperature类,将温度从f转换为c,反之亦然。测试用例是:

Temperature.new(:f => 32).in_celsius #=> 0

我认为通过:f => 32会给出转换。我不知道如何从哈希32中提取值:f => 32。我想提取它,以便我可以将该数字转换为f或c。

以下是我的答案代码。

class Temperature      
  def initialize(f = 0, c = 0)
    @f = f
    @c = c 
  end

  def in_fahrenheit
    c = @c * 1.8
    c += 32
    @f = c.floor
    @f 
  end

  def in_celsius
    f = @f - 32
    f /= 1.8
    @c = f.floor
    @c 
  end

  def fahrenheit
    @f 
  end 

  def celsius
    @c 
  end
end

我不熟悉在创建对象时作为初始值传递的哈希。我很感激任何建议。

3 个答案:

答案 0 :(得分:3)

您的import random try: userin = int(input("Enter the number of desired coin flips: ")) except ValueError: print("Invalid Input") coin = ['H', 'T'] userlist =(random.choices((coin), k=userin)) print('You flipped ' + str(userlist.count('H')) + ' Heads and ' + str(userlist.count('T')) + ' Tails.') print(userlist) k="" for x in range(0, len(userlist)): k=str(k) +"" + str(userlist.pop()) print(k) 方法正在查找两个参数,但您的输入只包含一个哈希值。以下是处理包含华氏度的哈希的方法:

initialize

如果您想要处理F或C中的输入,我会将其留作练习。

答案 1 :(得分:1)

如果我是你,我想我会这样做:

class Temperature

  def initialize(input)
    puts "in #{self.class}.#{__method__}, input.class.name is: #{input.class.name}"
    @f, @c = input[:f], input[:c]
  end

  def in_fahrenheit
    return @f if @f
    c = @c * 1.8
    c += 32
    @f = c.floor
    @f 
  end

  def in_celsius
    return @c if @c
    f = @f - 32
    f /= 1.8
    @c = f.floor
    @c 
  end

  def fahrenheit
    return @f if @f
    in_fahrenheit
  end 

  def celsius
    return @c if @c
    in_celsius
  end

end

正如马克·托马斯指出的那样,initialize正在收到Hash

> t = Temperature.new(f: 32)
in Temperature.initialize, input.class.name is: Hash
 => #<Temperature:0x0000000996cbf8 @f=32, @c=nil> 

BTW,f: 32:f => 32更现代,我相信。

我添加了一些return语句。这样,你可以这样做:

> t = Temperature.new(f: 32)
 => #<Temperature:0x00000009856ca0 @f=32, @c=nil> 
> t.fahrenheit
 => 32 
> t.celsius
 => 0 
> t.in_fahrenheit
 => 32
> t.in_celsius
 => 0 

> t = Temperature.new(c: 0)
 => #<Temperature:0x0000000986b038 @f=nil, @c=0> 
> t.fahrenheit
 => 32 
> t.celsius
 => 0 
> t.in_fahrenheit
 => 32 
> t.in_celsius
 => 0 

正如Mark所说,你可以做:

t = Temperature.new(f: 32, c: 32)

但是,这会给你带来各种错误的结果。所以,如果你想要防止这种情况,你可以这样做:

class Temperature

  def initialize(input)
    puts "in #{self.class}.#{__method__}, input.class.name is:"<<" #{input.class.name}"
    @f, @c = input[:f], input[:c]
    raise "Only one input, please!" if @f and @c
  end

  def in_fahrenheit
    return @f if @f
    c = @c * 1.8
    c += 32
    @f = c.floor
    @f 
  end

  def in_celsius
    return @c if @c
    f = @f - 32
    f /= 1.8
    @c = f.floor
    @c 
  end

  def fahrenheit
    return @f if @f
    in_fahrenheit
  end 

  def celsius
    return @c if @c
    in_celsius
  end

end

这会给你类似的东西:

> t = Temperature.new(f: 32, c: 0)
in Temperature.initialize, input.class.name is: Hash
RuntimeError: Only one input, please!

答案 2 :(得分:0)

你错误地混合了不同的参数样式。

位置参数

根据您的电话Temperature.new(:f => 32)判断,您似乎认为def initialize(f = 0, c = 0)提供了哈希或关键字参数。它没有。这只是两个位置参数(默认值,所以它们是可选的)。让我们打印出我们看到的结果:

  def initialize(f = 0, c = 0)
    puts "f is #{f.inspect}"
    puts "c is #{c.inspect}"
  end

您的电话:

Temperature.new(:f => 32)
f is {:f=>32}
c is 0

显然,这不是你想要的,以及为什么你以后会收到错误。以下是您必须打电话的方式:

Temperature.new(32)
f is 32
c is 0

Temperature.new(0, 32)
f is 0
c is 32

顺便说一下,nil0更好,因为0是完全有效的温度。并且必须提供一些f值才能提供c值。

Hash Argument

上面我们看到Ruby为你创建了一个哈希值,然后成为了方法得到的参数。因此,您可以更改方法签名以反映该方法,即获取哈希值,然后从中提取值:

  def initialize(options)
    f = options[:f]
    c = options[:c]
    puts "f is #{f.inspect}"
    puts "c is #{c.inspect}"
  end

现在你可以像使用它一样使用它:

Temperature.new(:f => 32)
f is 32
c is nil

Temperature.new(:c => 32)
f is nil
c is 32

请注意,这样您就可以获得nil作为默认值。您还可以使用这种更好的语法:

Temperature.new(f: 32)
f is 32
c is nil

Temperature.new(c: 32)
f is nil
c is 32

关键字参数

差不多五年前,Ruby 2 came out and brought us keyword arguments。现在,Ruby不仅可以为您创建哈希,而且还可以告诉您将它拆开。像这样:

  def initialize(f: nil, c: nil)
    puts "f is #{f.inspect}"
    puts "c is #{c.inspect}"
  end

你仍然可以像以前一样打电话:

Temperature.new(f: 32)
f is 32
c is nil

Temperature.new(c: 32)
f is nil
c is 32

initialize(f: nil, c: nil)看起来没有initialize(options)更有意义吗?它甚至看起来非常像现在的电话。而且您不需要额外的代码来从哈希中提取值。此外,如果您输入参数名称错误,则现在会收到错误:

Temperature.new(x: 32)
ArgumentError: unknown keyword: x

单个哈希参数解决方案只需将fc设置为nil,并愉快地继续前进,就像没有问题一样。

你甚至可以使用显式哈希和火箭表示法来调用它,尽管我只是为了进一步理解而表明:

Temperature.new({:f => 32})
f is 32
c is nil