我正在使用实例方法创建一个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
我不熟悉在创建对象时作为初始值传递的哈希。我很感激任何建议。
答案 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
顺便说一下,nil
比0
更好,因为0
是完全有效的温度。并且必须提供一些f
值才能提供c
值。
上面我们看到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
单个哈希参数解决方案只需将f
和c
设置为nil
,并愉快地继续前进,就像没有问题一样。
你甚至可以使用显式哈希和火箭表示法来调用它,尽管我只是为了进一步理解而表明:
Temperature.new({:f => 32})
f is 32
c is nil