【问题标题】:Checking if a variable is defined?检查是否定义了变量?
【发布时间】:2010-09-22 06:27:34
【问题描述】:

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

【问题讨论】:

    标签: ruby reflection


    【解决方案1】:

    defined?(your_var) 可以。根据你在做什么,你也可以做类似your_var.nil?

    【讨论】:

    • +1 表示 your_var.nil?,因为它返回 true 或 false,并且比 defined? var 更易于读写。谢谢你。
    • your_var.nil? 将导致错误:undefined local variable or method your_var 之前未定义...
    【解决方案2】:

    使用 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)
    【解决方案3】:

    如果你想在它存在时什么都不做,但如果它不存在就创建它,这很有用。

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

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

    【讨论】:

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

    这是一些代码,没有什么火箭科学,但它运行良好

    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? 是可选的。
    【解决方案5】:

    上述语句的正确语法是:

    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 比使用比较运算符更“面向对象”。两者都不难阅读,所以使用任何一个可以帮助您发布更多产品。
    • 你指的是哪个声明?!?不要将答案用作对其他内容的评论。
    【解决方案6】:

    你可以试试:

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

    因为它返回一个布尔值。

    【讨论】:

    • SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
    • 使用unless 语句似乎过于复杂
    【解决方案7】:

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

    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
    【解决方案8】:

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

    【讨论】:

      【解决方案9】:

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

      $ 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 块中时,我感到很困惑。
      【解决方案10】:

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

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

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

      希望这会有所帮助! :)

      【讨论】:

        【解决方案11】:

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

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

        › 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
        

        【讨论】:

          【解决方案12】:

          警告回复:常见的 Ruby 模式

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

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

          考虑这种常见的红宝石模式:

           def method1
              @x ||= method2
           end
          
           def method2
              nil
           end
          

          method2 总是返回 nil。第一次调用 method1 时,@x 变量未设置 - 因此将运行 method2。 而method2 将设置@xnil。那很好,一切都很好。但是第二次拨打method1会发生什么?

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

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

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

          魔鬼在细节中:但您可以使用defined? 方法避开潜伏的鲨鱼。

          【讨论】:

          • 你是完全正确的,感谢您强调这一特定警告
          【解决方案13】:

          应该提到的是,使用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')
          

          【讨论】:

            【解决方案14】:

            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
            

            【讨论】:

              【解决方案15】:

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

              当变量不存在时:

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

              当变量确实存在时

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

              【讨论】:

                猜你喜欢
                • 2015-05-01
                • 2021-04-21
                • 2021-10-03
                • 2012-01-20
                • 2017-01-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多