Bir değişkenin tanımlanıp tanımlanmadığını kontrol etmek ister misiniz?


581

Ruby'de bir değişkenin tanımlanıp tanımlanmadığını nasıl kontrol edebilirim? issetMevcut bir -tip yöntemi var mı?

Yanıtlar:


791

defined?Anahtar kelimeyi kullanın ( belgeler ). Öğenin türünü içeren bir Dize döndürür ( nilyoksa).

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

Skalee'nin yorumladığı gibi: "Nil olarak ayarlanan değişkenin başlatıldığını belirtmek gerekir."

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

92
Bu ayarlanmış olduğunu değişken dikkati çekiyor nil edilir başlatıldı.
skalee

7
Değişken yoksa bir değişken ayarlamak ve eğer varsa değişkeni bırakmak istiyorsanız, aşağıdaki @ danmayer'ın cevabına ( ||=operatörün dahil olduğu) bakınız.
jrdioko

2
İşte içine girebileceğim başka bir tuhaflık .. Bir if-bloğunda koşulun hiç karşılanmadığı defined?bir değişken tanımlarsanız, o blok içinde tanımlanan bir değişken için hala true değerini döndürür!
elsurudo

1
defined?Boole döndüren böyle bir yöntem var mı ?
stevec

Doğru / yanlış dönmek için,!!defined?(object_name)
stevec

91

Eğer varsa hiçbir şey yapmak istemiyorsanız, eğer yoksa yaratın.

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

Bu, yeni örneği yalnızca bir kez oluşturur. Bundan sonra sadece var döndürmeye devam ediyor.


9
Bu da çok deyimsel Ruby ve bu arada çok tipik.
jrdioko

38
Sadece ||=boolean değerlerle kullanmayın , karışıklığın acısını hissetmeyin.
Andrew Marshall

6
@AndrewMarshall söylediklerini birlikte döndürebilir şeyle bu deyim önlemek nilyanı sen sürece gerçekten buna dönüşünü yaptığında deniyor ifadeyi her zaman değerlendirmek istediğiniznil
nzifnab

1
Eğer varsa vardır : boolelerde ile çalışan ve değişken açıkça false olarak ayarlanır değildi, varsayılan değer true olmak istiyorum, bu inşaat kullanabilirsiniz var = (var or var.nil?)
Tony Zito

1
@ArnaudMeuret Gerçekten değil. - aynı görünmese de, bu sorunun cevabını okumaya değer.
Monica'nın Davası

70

Yukarıdaki ifade için doğru sözdizimi:

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) değişkeninizle değiştirilir. Bu sözdizimi, if ifadesinde değerlendirme için doğru / yanlış değeri döndürür.


11
Nil, bir testte kullanıldığında yanlış olarak değerlendirdiği için gerekli değildir
Jerome

Neden olmasın defined?(var) == nil?
vol7ron

@ vol7ron - Bu tamamen geçerli bir sözdizimidir. .nil?Dedikleri gibi çağrıyı kullanmak daha deyimseldir. Bir nesneye nilkarşılaştırma operatörü kullanmaktan ziyade sormak daha "nesne yönelimlidir" . İkisini de okumak zor, bu yüzden hangisini daha fazla ürün göndermenize yardımcı olursa kullanın.
juanpaco

Hangi ifadeye atıfta bulunuyorsunuz?!? Bir yanıtı başka bir şeye yorum olarak kullanmayın.
Arnaud Meuret

18

defined?(your_var)çalışacak. Ne yaptığınıza bağlı olarak şöyle bir şey de yapabilirsinizyour_var.nil?


+1 için your_var.nil?false değerini döndürdüğü ve okumak ve yazmaktan çok daha hoş olduğu için defined? var. Bunun için teşekkürler.
kakubei

28
your_var.nil?hataya neden olur: daha undefined local variable or method your_varönce tanımlanmadığında ...
Gobol

16

"İf" yerine "unless" komutunu deneyin

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

Diğer cevaplar tarafından söylenmeyen bu cevap ne ekliyor?
Andrew Grimm

2
Soruyu daha kullanışlı bir şekilde çok güzel bir şekilde cevaplıyor, değil mi?
look

2
Yakut tarzı rehber "Olumsuz koşullar için bitmedikçe
lehine

9

Kullanımı defined? YourVariable
basit aptalca tutun ..;)


8

İşte bazı kod, roket bilimi yok ama yeterince iyi çalışıyor

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

Açıkça, renklendirme kodu gerekli değildir, bu oyuncak örneğinde sadece güzel bir görselleştirme.


Muhtemelen çünkü nil?isteğe bağlıdır.
James

8

UYARI Re: Ortak Bir Yakut Deseni

Bu anahtar cevap: defined?yöntem. Yukarıdaki kabul edilen cevap bunu mükemmel bir şekilde göstermektedir.

Ama dalgaların altında gizlenen bir köpekbalığı var ...

Bu tür ortak yakut desenini düşünün:

 def method1
    @x ||= method2
 end

 def method2
    nil
 end

method2her zaman geri döner nil. Aradığınızda İlk kez method1, @xdeğişken ayarlı değil - bu nedenle method2işletilecek. ve method2ayarlayacaktır @xiçin nil. Bu iyi ve her şey yolunda ve güzel. Fakat ikinci aradığınızda ne olur method1?

@X'in zaten sıfır olarak ayarlandığını unutmayın. But method2yine tekrar çalıştırılacak !! Method2 maliyetli bir girişim ise, bu istediğiniz bir şey olmayabilir.

defined?Yöntemin kurtarmaya gelmesine izin verin - bu çözümle, bu özel durum ele alınır - aşağıdakileri kullanın:

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

Şeytan ayrıntılarda gizlidir: ancak defined?yöntemle gizlenen köpekbalığından kaçabilirsiniz .


Tamamen haklısınız, bu özel uyarıyı vurguladığınız için teşekkür ederiz
Kulgar

5

Deneyebilirsin:

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

Çünkü bir boole döndürür.


SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
Andrew Grimm

bir unlessifade kullanmak aşırı karmaşık görünüyor
johannes

5

Diğer birçok örnekte gösterildiği gibi, yakutta mantıksal seçimler yapmak için bir yöntemden bir boole gerek yoktur. Aslında bir boole ihtiyacınız olmadığı sürece her şeyi bir boole zorlamak kötü bir form olacaktır.

Ama kesinlikle bir boole ihtiyacınız varsa. Kullanın !! (bang bang) veya "falsy falsy gerçeği ortaya çıkarır".

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

Neden genellikle baskı için ödeme yapmıyor:

>> (!!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

Burada önemli olan bir örnek var, çünkü boole değerinin dize temsiline örtülü zorlamasına dayanıyor.

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

3

definedBir hash içinde belirli bir alanın ayarlanıp ayarlanmadığını kontrol etmek için kullanmanın beklenmedik davranabileceğini belirtmek gerekir :

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

Sözdizimi burada doğrudur, ancak defined? var['unknown']dizeye göre değerlendirilir "method", böylece ifblok yürütülür

edit: Bir anahtar bir karma içinde olup olmadığını kontrol etmek için doğru gösterim olurdu:

if var.key?('unknown')

2

Lütfen "tanımlı" ve "atanmış" arasındaki farkı not edin.

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

x asla atanmamış olmasına rağmen tanımlanır!


Bu yeni karşılaştığım bir şey. Bekliyordum NameError Exception: undefined local variable or methodve değişkenin tek ataması / sözü, isabet alamayan bir if bloğunda olduğunda kafası karışmıştı.
Paul Pettengill

0

Ayrıca, kod yazarsanız, bir dizede iken enterpolasyon yoluyla tanımlanıp tanımlanmadığını kontrol edebilirsiniz:

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

Sistem tanımlanmışsa size türü söyleyecektir. Tanımlanmamışsa, değişkenin başlatılmadığını belirten bir uyarı döndürür.

Bu yardımcı olur umarım! :)


0

defined?harika, ancak bir Rails ortamındaysanız try, özellikle dinamik bir değişken adını kontrol etmek istediğiniz durumlarda da kullanabilirsiniz :

foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo)        # => 1
try(:bar)        # => nil
try(my_foo)      # => 1
try(my_bar)      # => nil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.