2008-10-23 37 views
33

Tôi mới dùng ruby ​​và đang chơi với IRB.Làm thế nào để bạn liệt kê các đối tượng hiện có sẵn trong phạm vi hiện tại trong ruby?

Tôi thấy rằng tôi có thể liệt kê các phương thức của một đối tượng bằng cách sử dụng phương thức ".methods", và self.methods đó cung cấp cho tôi những gì tôi muốn (tương tự với thư mục Python (builtins)?), Tôi tìm thấy các phương pháp của một thư viện/mô-đun tôi đã tải thông qua bao gồm và yêu cầu?

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> 

Tôi đã quen với trăn, nơi tôi sử dụng dir() chức năng để thực hiện điều tương tự:

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

Trả lời

25

ObjectSpace.each_object có thể là những gì bạn đang tìm kiếm.

Để có danh sách các mô-đun đi kèm, bạn có thể sử dụng Module.included_modules.

Bạn cũng có thể kiểm tra xem đối tượng có phản hồi phương pháp theo từng trường hợp hay không bằng cách sử dụng object.respond_to?.

0

Bạn có thể vượt qua các thông điệp .methods đến thư viện/module ngay cả trước khi tải nó, để xem tất cả các phương pháp có sẵn. Làm self.methods chỉ trả về tất cả các phương thức mà đối tượng Object chứa. Bạn có thể thấy điều này bằng cách thực hiện self.class. Vì vậy, giả sử bạn muốn xem tất cả các phương thức trong mô-đun Tệp. Bạn chỉ cần thực hiện File.methods và bạn sẽ nhận được danh sách tất cả các phương thức tồn tại trong mô-đun Tệp. Điều này, có lẽ, không phải là những gì bạn muốn, nhưng nó sẽ được phần nào hữu ích.

2

Để truy cập vào tất cả các trường đối tượng trong ruby ​​bạn sử dụng ObjectSpace

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

Tuy nhiên, điều này được coi là chậm (ngay cả đối với ruby), và có thể không được cho phép trong một số dịch viên (ví dụ JRuby có thể vô hiệu hóa ObjectSpace như nó nhanh hơn nhiều trong jvm cho gc mà không cần phải theo dõi công cụ này trong jRuby).

5

Phương pháp dir()not clearly defined ...

Lưu ý:dir() được cung cấp chủ yếu như là một tiện nghi để sử dụng ở một dấu nhắc tương tác, nó cố gắng cung cấp một bộ thú vị của tên nhiều hơn nó cố gắng cung cấp một cách chặt chẽ hoặc nhất quán được xác định đặt tên và hành vi chi tiết của nó có thể thay đổi trên toàn bộ bản phát hành.

... nhưng chúng tôi có thể tạo xấp xỉ gần đúng trong Ruby. Hãy tạo một phương thức sẽ trả về một danh sách được sắp xếp của tất cả các phương thức được thêm vào phạm vi của chúng ta bằng các mô-đun đi kèm. Chúng ta có thể nhận được một danh sách các mô-đun đã được bao gồm bằng cách sử dụng phương thức included_modules.

Giống như dir(), chúng tôi muốn bỏ qua các phương thức "mặc định" (như print) và chúng tôi cũng muốn tập trung vào nhóm tên "thú vị". Vì vậy, chúng ta sẽ bỏ qua các phương thức trong Kernel và chúng tôi sẽ chỉ trả lại các phương thức đã được xác định trực tiếp trong các mô-đun, bỏ qua các phương thức kế thừa. Chúng tôi có thể thực hiện sau bằng cách chuyển số false vào phương thức methods(). Đặt tất cả cùng nhau, chúng tôi nhận được ...

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 

Bạn có thể chuyển cho lớp, đối tượng hoặc không có gì (mặc định là phạm vi hiện tại). Hãy thử nó ra ...

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() cũng bao gồm các biến được xác định tại địa phương, và đó là một điều dễ dàng. Chỉ cần gọi ...

local_variables 

... không may, chúng ta không thể chỉ cần thêm local_variables cuộc gọi đến included_methods bởi vì nó sẽ cho chúng ta những biến là cục bộ đối phương included_methods, và điều đó sẽ không phải là rất hữu ích. Vì vậy, nếu bạn muốn biến cục bộ kèm với included_methods, chỉ cần gọi ...

(included_methods + local_variables).sort 
+0

ok, tôi đang học chậm. Điều này mang lại câu hỏi tiếp theo của tôi, sự khác biệt giữa "bao gồm" và "yêu cầu" là gì? Tôi sẽ đi làm một số đọc, nhưng làm thế nào có thể được nhìn thấy phương pháp được tải thông qua "yêu cầu"? – monkut

+1

Bao gồm sẽ thêm các hằng số, phương thức và biến mô đun vào phạm vi hiện tại. Nó thường được sử dụng để thêm chức năng cho một lớp. A yêu cầu tải một tệp ruby ​​khác (nếu nó chưa được tải). Nếu bạn muốn tải nó (ngay cả khi nó đã được tải), hãy sử dụng phương thức "tải" thay thế. –

+0

Thông thường một tệp được yêu cầu sẽ tải một lớp. Ví dụ, yêu cầu 'foo' sẽ tải các lớp Foo. Vì vậy, bạn có thể nhận được một danh sách các phương thức trong lớp đó bằng cách thực hiện Foo.methods (false). Nếu tệp được yêu cầu chỉ là một loạt các phương thức: orig = Object.private_methods; yêu cầu 'foo'; p Object.private_methods - orig –

39

Tôi không hoàn toàn chắc chắn về những gì bạn có nghĩa là do 'đối tượng hiện tại'. Bạn có thể lặp qua ObjectSpace, như đã được đề cập. Nhưng đây là một vài phương pháp khác.

local_variables 
instance_variables 
global_variables 

class_variables 
constants 

Có một hình ảnh xác thực. Chúng phải được gọi ở đúng phạm vi. Vì vậy, ngay trong IRB, hoặc trong một trường hợp đối tượng hoặc ở phạm vi lớp (vì vậy ở khắp mọi nơi, về cơ bản), bạn có thể gọi là người đầu tiên 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", ...] 

Nhưng umm, nếu bạn muốn chương trình của bạn để thực sự đánh giá chúng mà không cần bạn để nhập chúng nhiều? Bí quyết là eval.

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

2 cuối cùng được đề cập ở đầu phải được đánh giá ở cấp mô-đun (lớp là hậu duệ của mô-đun, để hoạt động).

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" 

đây của một vài chi tiết thủ thuật để khám phá các hướng khác nhau

"".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

tôi đã viết một viên ngọc cho rằng:

$ 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 

tôi đang làm việc trên một sự cải tiến các lựa chọn đi qua và các thiết lập mặc định, nhưng hiện tại tôi khuyên bạn nên thêm thông tin sau vào tệp .irbrc của bạn:

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

Điều này cho phép màu sắc và ẩn các phương thức mà mọi đối tượng đều có, vì bạn thường không quan tâm đến những đối tượng đó.

+2

Tôi đoán đó không thực sự là câu hỏi về nhưng oh jeebus là thứ mà tôi cần cho irb. Việc sử dụng rộng rãi các mixin dẫn đến quá nhiều phương pháp làm cho các thư viện ruby ​​khó khám phá nhiều hơn python, nhưng điều này sẽ rất độc đáo giúp bạn sắp xếp thông qua đó. Bây giờ tôi chỉ cần một sự thay thế để được giúp đỡ() đó là tốt. –

1

gì về:

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

Đó liệt kê các lớp học dành cho tôi. Tôi không phải là chuyên gia ruby ​​và tôi đã bị bỏ rơi ở một bàn điều khiển ruby ​​mà không biết lớp học nào đang ở trong tầm tay. Đó là một lớp lót là một sự khởi đầu.

Các vấn đề liên quan