检查是否定义了变量?

Rea*_*nly 571 ruby reflection

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

Ric*_*ras 782

使用defined?关键字(文档).它将返回一个带有项目类型的String,或者nil它是否不存在.

>> a = 1
 => 1
>> defined? a
 => "local-variable"
>> defined? b
 => nil
>> defined? nil
 => "nil"
>> defined? String
 => "constant"
>> defined? 1
 => "expression"
Run Code Online (Sandbox Code Playgroud)

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

>> n = nil  
>> defined? n
 => "local-variable"
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,设置为"nil"*的变量是*初始化的. (87认同)
  • 如果你想设置一个变量(如果它不存在的话),如果它存在则不管它,请参阅下面的@ danmayer的答案(涉及`|| =`运算符). (7认同)
  • 那太过分了. (2认同)
  • 这是我可以进入的另一个奇怪之处.. 如果你在一个条件不满足的 if 块中定义一个变量,`defined?` 仍然为该块中定义的变量返回 true! (2认同)
  • 是否有像 `define?` 这样返回布尔值的方法? (2认同)

dan*_*yer 91

如果您确实存在则不执行任何操作,但如果它不存在则创建它,这将非常有用.

def get_var
  @var ||= SomeClass.new()
end
Run Code Online (Sandbox Code Playgroud)

这只会创建一次新实例.之后它只是继续返回var.

  • 只是不要使用带有布尔值的`|| =`,以免感到困惑的痛苦. (38认同)
  • 顺便说一句,这也是非常惯用的Ruby,非常典型. (9认同)
  • 和@AndrewMarshall所说的一样,避免这个习惯用任何可能返回"nil"的内容,除非你*真的*想要在每次调用它时返回`nil'时调用表达式 (6认同)

小智 70

上述语句的正确语法是:

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
Run Code Online (Sandbox Code Playgroud)

var用你的变量替换().此语法将在if语句中返回true/false值以进行评估.

  • 这不是必需的,因为在测试中使用时,nil评估为false (11认同)

dig*_*tum 18

defined?(your_var)将工作.根据你正在做的事情,你也可以做类似的事情your_var.nil?

  • `your_var.nil?`会导致错误:`未定义的局部变量或方法your_var`如果之前未定义... (27认同)

小智 15

尝试"除非"而不是"如果"

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
Run Code Online (Sandbox Code Playgroud)

  • 它以一种更有用的方式很好地回答了这个问题,不是吗? (2认同)
  • 红宝石风格指南说"除非为负面条件,否则支持"https://github.com/bbatsov/ruby-style-guide (2认同)

Saq*_* R. 9

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


Sar*_*ica 7

这里有一些代码,没有什么火箭科学,但它运作得很好

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
Run Code Online (Sandbox Code Playgroud)

显然,着色代码不是必需的,只是这个玩具示例中的一个很好的视觉效果.

  • @James:真的吗?Downvote而不是编辑和改变?.... meh,没关系.^ _〜 (5认同)

BKS*_*eon 6

警告Re:常见的Ruby模式

这是关键答案:defined?方法.上面接受的答案完美地说明了这一点

但是有一条鲨鱼潜伏在海浪下面......

考虑这种类型的常见ruby模式:

 def method1
    @x ||= method2
 end

 def method2
    nil
 end
Run Code Online (Sandbox Code Playgroud)

method2总是回来nil.第一次调用时method1,@x变量未设置 - 因此method2将运行.并且method2将设置@xnil.那很好,一切都很好.但是第二次打电话会发生什么method1

记住@x已经设置为nil.But method2仍将再次运行!! 如果method2是一项代价高昂的工作,那么这可能不是您想要的.

defined?方法得到解决 - 使用此解决方案,处理特定情况 - 使用以下内容:

  def method1
    return @x if defined? @x
    @x = method2
  end
Run Code Online (Sandbox Code Playgroud)

魔鬼在细节中:但是你可以用这种defined?方法躲避潜伏的鲨鱼.


小智 5

你可以试试:

unless defined?(var)
  #ruby code goes here
end
=> true
Run Code Online (Sandbox Code Playgroud)

因为它返回一个布尔值.


小智 5

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

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

› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Run Code Online (Sandbox Code Playgroud)

为什么它通常不支付强制:

>> (!!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
Run Code Online (Sandbox Code Playgroud)

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

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