ChatGPT解决这个技术问题 Extra ChatGPT

检查是否定义了变量?

如何检查变量是否在 Ruby 中定义?是否有可用的 isset 类型方法?


a
akuhn

使用 defined? 关键字 (documentation)。它将返回一个带有项目类型的字符串,如果不存在则返回 nil

>> a = 1
 => 1
>> defined? a
 => "local-variable"
>> defined? b
 => nil
>> defined? nil
 => "nil"
>> defined? String
 => "constant"
>> defined? 1
 => "expression"

正如 skalee 评论的那样:“值得注意的是,设置为 nil 的变量已被初始化。”

>> n = nil  
>> defined? n
 => "local-variable"

值得注意的是,设置为 nil 的变量已初始化。
如果您想设置不存在的变量,如果存在则不处理,请参阅下面的@danmayer 的答案(涉及 ||= 运算符)。
这是我能想到的另一个奇怪之处。如果您在条件从未满足的 if 块中定义一个变量,defined? 仍然为该块中定义的变量返回 true!
有没有像 defined? 这样返回布尔值的方法?
要返回真/假,!!defined?(object_name)
A
Arnaud Meuret

如果您想在它确实存在时不做任何事情但如果它不存在则创建它,这很有用。

def get_var
  @var ||= SomeClass.new()
end

这只会创建一次新实例。之后,它只是不断返回 var。


顺便说一句,这也是非常惯用的 Ruby 并且非常典型。
只是不要将 ||= 与布尔值一起使用,以免您感到困惑的痛苦。
与@AndrewMarshall 所说的一样,避免使用任何可能返回 nil 的惯用语,除非您真的想要在每次调用它时评估表达式返回 nil
如果您正在使用布尔值,并且希望在变量未明确设置为 false 的情况下默认值为 true,则可以使用以下构造:var = (var or var.nil?)
@ArnaudMeuret Sort of, not really. - 虽然它可能看起来不一样,但值得阅读该问题的答案。
T
True Soft

上述语句的正确语法是:

if (defined?(var)).nil? # will now return true or false
 print "var is not defined\n".color(:red)
else
 print "var is defined\n".color(:green)
end

用您的变量替换 (var)。此语法将返回真/假值以在 if 语句中进行评估。


这不是必需的,因为在测试中使用 nil 时评估为 false
为什么不 defined?(var) == nil
@vol7ron - 这是完全有效的语法。正如他们所说,使用对 .nil? 的调用更为惯用。询问对象是否为 nil 比使用比较运算符更“面向对象”。两者都不难阅读,所以使用任何一个可以帮助您发布更多产品。
你指的是哪个声明?!?不要将答案用作对其他内容的评论。
d
digitalsanctum

defined?(your_var) 将起作用。根据您的操作,您还可以执行 your_var.nil? 之类的操作


your_var.nil? +1,因为它返回 true 或 false,并且比 defined? var 更易于读写。谢谢你。
your_var.nil? 将导致错误:undefined local variable or method your_var 之前未定义...
T
Taymon

尝试“除非”而不是“如果”

a = "apple"
# Note that b is not declared
c = nil

unless defined? a
    puts "a is not defined"
end

unless defined? b
    puts "b is not defined"
end

unless defined? c
    puts "c is not defined"
end

这个答案增加了其他答案没有说的什么?
它以一种更有用的方式很好地回答了这个问题,不是吗?
红宝石风格指南说“赞成,除非在负面条件下结束”github.com/bbatsov/ruby-style-guide
B
BenKoshy

警告回复:常见的 Ruby 模式

这是关键答案:defined? 方法。 accepted answer above 完美地说明了这一点。

但是有一条鲨鱼,潜伏在海浪之下……

考虑一下这种常见的 ruby 模式:

 def method1
    @x ||= method2
 end

 def method2
    nil
 end

method2 总是返回 nil。第一次调用 method1 时,未设置 @x 变量 - 因此将运行 method2。并且method2会将@x设置为nil。

但是第二次调用 method1 会发生什么?

记住 @x 已经被设置为 nil。但 method2 仍将再次运行!!如果方法 2 是一项昂贵的工作,那么这可能不是您想要的。

defined? 方法来拯救:

  def method1
    return @x if defined? @x
    @x = method2
  end

与大多数事情一样,魔鬼在实施细节中。


你是完全正确的,谢谢你强调这个具体的警告
S
Saqib R.

使用defined? YourVariable
保持简单傻 .. ;)


S
Sardathrion - against SE abuse

这是一些代码,没有什么火箭科学,但效果很好

require 'rubygems'
require 'rainbow'
if defined?(var).nil?  # .nil? is optional but might make for clearer intent.
 print "var is not defined\n".color(:red)
else
 print "car is defined\n".color(:green)
end

显然,着色代码不是必需的,在这个玩具示例中只是一个很好的可视化。


大概是因为 nil? 是可选的。
H
Haris Krajina

你可以试试:

unless defined?(var)
  #ruby code goes here
end
=> true

因为它返回一个布尔值。


SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
使用 unless 语句似乎过于复杂
d
donnoman

正如许多其他示例所示,您实际上并不需要方法中的布尔值来在 ruby 中进行逻辑选择。除非您确实需要布尔值,否则将所有内容强制为布尔值将是一种糟糕的形式。

但是如果你绝对需要一个布尔值。利用 !! (砰砰)或“假假揭示真相”。

› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false

为什么强迫通常不值得:

>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true

这是一个重要的示例,因为它依赖于布尔值对其字符串表示的隐式强制。

>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil

l
leberknecht

应该提到的是,使用 defined 检查是否在哈希中设置了特定字段可能会出现意外行为:

var = {}
if defined? var['unknown']
  puts 'this is unexpected'
end
# will output "this is unexpected"

此处的语法是正确的,但 defined? var['unknown'] 将被评估为字符串 "method",因此将执行 if

编辑:检查哈希中是否存在密钥的正确表示法是:

if var.key?('unknown')

R
Robert Klemme

请注意“已定义”和“已分配”之间的区别。

$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"

x 被定义,即使它从未被分配!


这是我刚刚遇到的。我期待 NameError Exception: undefined local variable or method,但当变量的唯一赋值/提及位于未命中的 if 块中时,我感到很困惑。
J
John Donner

defined? 很好,但如果您在 Rails 环境中,您也可以使用 try,尤其是在您想要检查动态变量名的情况下:

foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo)        # => 1
try(:bar)        # => nil
try(my_foo)      # => 1
try(my_bar)      # => nil

这正是我想要的。如果 var 存在,我需要该值。谢谢!
E
Elliott

此外,您可以通过插值检查它是否在字符串中定义,如果您编写代码:

puts "Is array1 defined and what type is it? #{defined?(@array1)}"

如果定义了类型,系统会告诉您类型。如果它没有被定义,它只会返回一个警告说变量没有被初始化。

希望这可以帮助! :)


s
stevec

留下一个非常简单的例子,以防万一。

当变量不存在时:

if defined? a then "hi" end
# => nil

当变量确实存在时:

a = 2
if defined? a then "hi" end
# => "hi"