2008-10-23 9 views
33

Soy nuevo en ruby ​​y estoy jugando con el IRB.¿Cómo se enumeran los objetos actualmente disponibles en el alcance actual en ruby?

me encontré con que hacer una lista de métodos de un objeto utilizando el "método" .methods, y que self.methods especie de darme lo que quiero (similares a dir de Python (órdenes internas)?), Pero ¿cómo puede Me parece que los métodos de una biblioteca/módulo que he cargado a través de incluyen y requieren?

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> 

Estoy acostumbrado a pitón, donde utilizo la función dir() para obtener el mismo resultado:

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

Respuesta

0

Puede pasar los mensajes .methods a la biblioteca/módulo, incluso antes de la carga para ver todos los métodos disponibles Al hacer self.methods, solo devuelve todos los métodos que contiene el objeto Object. Puede ver esto haciendo self.class. Digamos que desea ver todos los métodos en el módulo Archivo. Simplemente haga File.methods y obtendrá una lista de todos los métodos que existen en el módulo Archivo. Esto, quizás, no es lo que quieres, pero debería ser de alguna ayuda.

2

Para tener acceso a todas las instancias de objetos en Ruby utiliza ObjectSpace

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

Sin embargo, esto se considera lento (incluso para rubí), y no se haga posible en algunos intérpretes (por ejemplo jruby puede desactivar ObjectSpace como es mucho más rápido confiar en el jvm para gc sin necesidad de seguir estas cosas en jRuby).

5

El método dir() es not clearly defined ...

Nota: Debido adir() se suministra principalmente como una conveniencia para el uso en un modo interactivo, se trata de suministrar un interesante conjunto de nombres más de lo que intenta proporcionar un conjunto definido rigurosamente o consistentemente de nombres, y su comportamiento detallado puede cambiar entre lanzamientos.

... pero podemos crear una aproximación cercana en Ruby. Hagamos un método que devuelva una lista ordenada de todos los métodos agregados a nuestro alcance por los módulos incluidos. Podemos obtener una lista de los módulos que se han incluido utilizando el método included_modules.

Como dir(), queremos ignorar los métodos "predeterminados" (como print), y también queremos centrarnos en el conjunto "interesante" de nombres. Por lo tanto, ignoraremos los métodos en Kernel, y solo devolveremos los métodos que se definieron directamente en los módulos, ignorando los métodos heredados. Podemos lograr el último pasando false en el método methods(). Poniendo todo junto, obtenemos ...

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 

Puede pasarle una clase, un objeto o nada (su valor predeterminado es el alcance actual). Vamos a probarlo ...

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() también incluye variables definidas localmente, y eso es una tarea fácil. Sólo tiene que llamar ...

local_variables 

... por desgracia, no podemos simplemente añadir la llamada a local_variablesincluded_methods porque nos daría las variables que son locales en el método included_methods, y que no sería muy útil. Por lo tanto, si quieres las variables locales que se incluyen con los included_methods, simplemente llame ...

(included_methods + local_variables).sort 
+0

bien, estoy aprendiendo despacio. Esto me lleva a mi siguiente pregunta, ¿cuál es la diferencia entre "incluir" y "requerir"? Iré a leer un poco, pero ¿cómo se pueden ver los métodos que se cargaron a través de "requerir"? – monkut

+1

Una inclusión agregará las constantes, los métodos y las variables de módulo al alcance actual. Normalmente se usa para agregar funcionalidad a una clase. A requieren cargar otro archivo ruby ​​(si aún no se ha cargado). Si desea cargarlo (incluso si ya está cargado) utilice el método de "carga" en su lugar. –

+0

Normalmente, un archivo requerido cargará una clase. Por ejemplo, require 'foo' cargará las clases Foo. Entonces, puedes obtener una lista de métodos en esa clase haciendo Foo.methods (falso). Si el archivo requerido es solo un conjunto de métodos: orig = Object.private_methods; requiere 'foo'; p Object.private_methods - orig –

39

No estoy del todo seguro de lo que quiere decir con los "objetos actuales. Puede iterar sobre ObjectSpace, como ya se ha mencionado. Pero aquí hay algunos otros métodos.

local_variables 
instance_variables 
global_variables 

class_variables 
constants 

Hay una gotcha. Deben ser llamados en los ámbitos correctos. Tan a la derecha en la IRB, o en una instancia de objeto o al ámbito de clase (por lo que en todas partes, básicamente) puede llamar a la primera 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", ...] 

Pero umm, lo que si desea que su programa para evaluar realmente los que sin necesidad para escribirlos de muchas maneras? El truco es eval.

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

las últimas 2 de los 5 mencionado al principio deben ser evaluados a nivel de módulo (una clase es un descendiente de un módulo, por lo que las obras).

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" 

Aquí hay unos cuantos más trucos para explorar en diferentes direcciones

"".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...", ...] 
5

que escribí una joya para que:

$ 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 ::: 
%, &, *, **, +, -, [email protected], /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, 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 ::: 
[email protected], 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 

estoy trabajando en una mejora de las opciones de pase y ajustes por defecto, pero por ahora le sugiero que agregue lo siguiente a su archivo .irbrc:

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

Esto habilita los colores y oculta los métodos que tiene cada objeto, ya que normalmente no le interesan.

+2

Supongo que de eso no se trata realmente la pregunta, pero oh jeebus es que esto es lo que necesitaba para irb. El uso extensivo de mixins que conduce a demasiados métodos hace que las bibliotecas de ruby ​​sean mucho más difíciles de explorar que las de Python, pero esto debería ayudar a resolverlo. Ahora solo necesito un reemplazo para la ayuda() que es igual de bueno. –

1

¿Qué hay de:

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

que las listas de clases disponibles para mí. No soy un experto en rubíes y estaba siendo arrojado a una consola de rubí sin tener idea de qué clases tenían a mano. Ese único trazador de líneas fue un comienzo.

Cuestiones relacionadas