如何在ruby中列出当前作用域中当前可用的对象?

时间:2008-10-23 05:38:16

标签: ruby introspection irb

我是红宝石的新手,我正在玩IRB。

我发现我可以使用“.methods”方法列出对象的方法,而self.methods类似于我想要的东西(类似于Python的目录( builtins )?) ,但是如何找到我通过include和require加载的库/模块的方法?

irb(main):036:0* self.methods
=> ["irb_pop_binding", "inspect", "taguri", "irb_chws", "clone", "irb_pushws", "public_methods", "taguri=", "irb_pwws",
"public", "display", "irb_require", "irb_exit", "instance_variable_defined?", "irb_cb", "equal?", "freeze", "irb_context
", "irb_pop_workspace", "irb_cwb", "irb_jobs", "irb_bindings", "methods", "irb_current_working_workspace", "respond_to?"
, "irb_popb", "irb_cws", "fg", "pushws", "conf", "dup", "cwws", "instance_variables", "source", "cb", "kill", "help", "_
_id__", "method", "eql?", "irb_pwb", "id", "bindings", "send", "singleton_methods", "popb", "irb_kill", "chws", "taint",
 "irb_push_binding", "instance_variable_get", "frozen?", "irb_source", "pwws", "private", "instance_of?", "__send__", "i
rb_workspaces", "to_a", "irb_quit", "to_yaml_style", "irb_popws", "irb_change_workspace", "jobs", "type", "install_alias
_method", "irb_push_workspace", "require_gem", "object_id", "instance_eval", "protected_methods", "irb_print_working_wor
kspace", "irb_load", "require", "==", "cws", "===", "irb_pushb", "instance_variable_set", "irb_current_working_binding",
 "extend", "kind_of?", "context", "gem", "to_yaml_properties", "quit", "popws", "irb", "to_s", "to_yaml", "irb_fg", "cla
ss", "hash", "private_methods", "=~", "tainted?", "include", "irb_cwws", "irb_change_binding", "irb_help", "untaint", "n
il?", "pushb", "exit", "irb_print_working_binding", "is_a?", "workspaces"]
irb(main):037:0>

我习惯了python,我使用dir()函数完成同样的事情:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>>

7 个答案:

答案 0 :(得分:40)

我不完全确定“当前对象”的含义。您可以迭代ObjectSpace,如前所述。但是这里有一些其他的方法。

local_variables
instance_variables
global_variables

class_variables
constants

有一个问题。必须在正确的范围内调用它们。因此,在IRB中,或在对象实例中或在类范围内(所以无处不在,基本上),您可以调用前3个。

local_variables #=> ["_"]
foo = "bar"
local_variables #=> ["_", "foo"]
# Note: the _ variable in IRB contains the last value evaluated
_ #=> "bar"

instance_variables  #=> []
@inst_var = 42
instance_variables  #=> ["@inst_var"]

global_variables    #=> ["$-d", "$\"", "$$", "$<", "$_", ...]
$"                  #=> ["e2mmap.rb", "irb/init.rb", "irb/workspace.rb", ...]

但是嗯,如果你希望你的程序实际评估它们而不需要你那么明智地输入它们怎么办?诀窍是eval。

eval "@inst_var" #=> 42
global_variables.each do |v|
  puts eval(v)
end

开头提到的5个中的最后2个必须在模块级别进行评估(类是模块的后代,因此有效)。

Object.class_variables #=> []
Object.constants #=> ["IO", "Duration", "UNIXserver", "Binding", ...]

class MyClass
  A_CONST = 'pshh'
  class InnerClass
  end
  def initialize
    @@meh = "class_var"
  end
end

MyClass.constants           #=> ["A_CONST", "InnerClass"]
MyClass.class_variables     #=> []
mc = MyClass.new
MyClass.class_variables     #=> ["@@meh"]
MyClass.class_eval "@@meh"  #=> "class_var"

以下是在不同方向探索的其他一些技巧

"".class            #=> String
"".class.ancestors  #=> [String, Enumerable, Comparable, ...]
String.ancestors    #=> [String, Enumerable, Comparable, ...]

def trace
  return caller
end
trace #=> ["(irb):67:in `irb_binding'", "/System/Library/Frameworks/Ruby...", ...]

答案 1 :(得分:25)

ObjectSpace.each_object可能就是您想要的。

要获取所包含模块的列表,您可以使用Module.included_modules

您还可以使用object.respond_to?检查对象是否根据具体情况对方法做出响应。

答案 2 :(得分:6)

dir()方法是not clearly defined ...

  

注意:因为提供了dir()   主要是为了方便使用   一个互动的提示,它试图   提供一组有趣的名字   超过它试图提供一个   严格或一致定义的集合   名称及其详细行为   可能会在不同版本之间发生变化。

...但我们可以在Ruby中创建一个近似的近似值。让我们创建一个方法,它将返回由包含的模块添加到我们的作用域的所有方法的排序列表。我们可以使用included_modules方法获取已包含的模块列表。

dir()一样,我们希望忽略“默认”方法(如print),我们也希望关注“有趣”的名称集。因此,我们将忽略Kernel中的方法,并且我们将仅返回在模块中直接定义的方法,而忽略继承的方法。我们可以通过将false传递到methods()方法来完成后续工作。总而言之,我们得到......

def included_methods(object=self)
  object = object.class if object.class != Class
  modules = (object.included_modules-[Kernel])
  modules.collect{ |mod| mod.methods(false)}.flatten.sort
end

您可以将类,对象或任何内容传递给它(默认为当前范围)。我们来试试吧......

irb(main):006:0> included_methods
=> []
irb(main):007:0> include Math
=> Object
irb(main):008:0> included_methods
=> ["acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cos", "cosh", "erf", "erfc", "exp", "frexp", "hypot", "ldexp", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh"]

dir()还包括本地定义的变量,这很容易。请致电......

local_variables

...遗憾的是,我们无法将local_variables调用添加到included_methods,因为它会为我们提供included_methods方法的本地变量,而且不会非常有用。因此,如果您想要包含included_methods的局部变量,只需调用...

 (included_methods + local_variables).sort

答案 3 :(得分:6)

我写了一个宝石:

$ gem install method_info
$ rvm use 1.8.7 # (1.8.6 works but can be very slow for an object with a lot of methods)
$ irb
> require 'method_info'
> 5.method_info
::: Fixnum :::
%, &, *, **, +, -, -@, /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, abs,
div, divmod, even?, fdiv, id2name, modulo, odd?, power!, quo, rdiv,
rpower, size, to_f, to_s, to_sym, zero?, |, ~
::: Integer :::
ceil, chr, denominator, downto, floor, gcd, gcdlcm, integer?, lcm,
next, numerator, ord, pred, round, succ, taguri, taguri=, times, to_i,
to_int, to_r, to_yaml, truncate, upto
::: Precision :::
prec, prec_f, prec_i
::: Numeric :::
+@, coerce, eql?, nonzero?, pretty_print, pretty_print_cycle,
remainder, singleton_method_added, step
::: Comparable :::
between?
::: Object :::
clone, to_yaml_properties, to_yaml_style, what?
::: MethodInfo::ObjectMethod :::
method_info
::: Kernel :::
===, =~, __clone__, __id__, __send__, class, display, dup, enum_for,
equal?, extend, freeze, frozen?, hash, id, inspect, instance_eval,
instance_exec, instance_of?, instance_variable_defined?,
instance_variable_get, instance_variable_set, instance_variables,
is_a?, kind_of?, method, methods, nil?, object_id, pretty_inspect,
private_methods, protected_methods, public_methods, respond_to?, ri,
send, singleton_methods, taint, tainted?, tap, to_a, to_enum, type,
untaint
 => nil

我正在努力改进传递选项和设置默认值,但是现在我建议您将以下内容添加到.irbrc文件中:

require 'method_info'
MethodInfo::OptionHandler.default_options = {
 :ancestors_to_exclude => [Object],
 :enable_colors => true
}

这可以启用颜色并隐藏每个对象所具有的方法,因为您通常对这些方法不感兴趣。

答案 4 :(得分:2)

要访问ruby中的所有对象实例,请使用ObjectSpace

http://www.ruby-doc.org/core-1.8.7/classes/ObjectSpace.html#M000928

然而,这被认为是缓慢的(即使对于ruby),并且可能在某些解释器中没有启用(例如,jRuby可以禁用ObjectSpace,因为它更快地依赖jvm for gc而不需要在jRuby中跟踪这些东西)。

答案 5 :(得分:2)

怎么样:

Object.constants.select{|x| eval(x.to_s).class == Class}

为我列出了可用的课程。我不是红宝石专家,我被丢弃在红宝石控制台,不知道手头有什么课程。那个班轮就是一个开始。

答案 6 :(得分:0)

即使在加载之前,您也可以将.methods消息传递给库/模块,以查看所有可用的方法。执行self.methods只返回Object对象包含的所有方法。你可以通过self.class来看到这一点。因此,假设您要查看“文件”模块中的所有方法。您只需执行File.methods,您将获得文件模块中存在的所有方法的列表。这可能不是你想要的,但它应该有所帮助。