Skip to content

instance_eval moves self, class_eval moves def

Level: 301 · for a reader who has seen Klass.class_eval { def ... } in a library and obj.instance_eval { @x } in a test and wants to know which one to write

One line: Both evals run a block with self set to the receiver; the difference is where a def inside lands — class_eval on a class defines instance methods, instance_eval on anything defines singleton methods of that thing — and Python, which has no way to change what self means, does the same jobs with exec, setattr, classmethod and types.MethodType.

A Ruby block remembers the self of the place it was written. instance_eval and class_eval are the two methods that override that memory and run the block with a different self: obj.instance_eval { @secret } reads an instance variable from outside, Klass.class_eval { ... } reopens a class you hold in a variable. What separates them is a second, quieter setting — the default definee, the class that a bare def inside the block adds a method to. class_eval (alias module_eval) sets both self and the definee to the class, so def makes an instance method. instance_eval sets self to the receiver and the definee to the receiver's singleton class, so def makes a method of that one object — and when the receiver is a class, "that one object" is the class, which is why Klass.instance_eval { def y } defines a class method. Both also take a string instead of a block; a string is compiled at run time and needs __FILE__ and __LINE__ to give errors a place to point at. instance_exec is instance_eval with arguments. The program measures each of these, then two things people trip over: what a block or a string can see, and why class klass is not a way to reopen a class held in a variable.

Verified output of instance_eval_and_class_eval_rb.rb — regenerated by tools/run_examples.py, never hand-typed.

 1. safe.instance_eval { @secret }                 42
 2. safe.instance_eval { self.class }              Safe
 3. Safe.class_eval { def x }: Safe.new.x          "instance x"
    Safe.x                                         NoMethodError: undefined method 'x' for class Safe
 4. Safe.instance_eval { def y }: Safe.y           "class y"
    Safe.new.y                                     NoMethodError: undefined method 'y' for an instance of Safe
 5. safe.instance_eval { def only_me }             safe.singleton_methods = [:only_me]
    Safe.new.respond_to?(:only_me)                 false
 6. safe.instance_exec(3) { |n| @secret + n }      45
    instance_eval { |o| o.equal?(safe) }           true
    instance_eval(&-> { 1 }) -- a strict lambda    ArgumentError: wrong number of arguments (given 1, expected 0)
 7. class_eval("def z = 3", __FILE__, __LINE__ + 1) source_location = instance_eval_and_class_eval_rb.rb:48
    class_eval("def w = 4") -- no file, no line    source_location = (eval at instance_eval_and_class_eval_rb.rb:49):1
 8. class_eval { factor * 2 } -- a block closes    6
 9. class_eval { 1 + 1 } / instance_eval("1 + 1")  2 / 2
10. blk = proc { self.class }; blk.call            Object
    safe.instance_eval(&blk)                       Safe
11. class klass; end -- a variable, not a constant SyntaxError
    klass.class_eval { def v = 5 }: klass.new.v    5
12. x = 5; eval("x + 1") -- the current scope      6
13. module_eval == class_eval (same method)        true

Reading the output

Rows 1 and 2: inside instance_eval the block's self is safe, so @secret is safe's variable and self.class is Safe. Rows 3 and 4 are the classic pair: class_eval { def x } gives every Safe an x and the class itself has none; instance_eval { def y } gives the class Safe a y and instances have none. Row 5 is the same rule on a plain object — the def landed on safe's singleton class, so safe.singleton_methods lists it and a second Safe does not respond. Row 6: instance_exec passes arguments; instance_eval passes exactly one, the receiver itself, which is why the block form { |o| ... } sees safe and why a zero-argument lambda — strict about its count — raises ArgumentError when handed to it. Row 7 is the string form: with __FILE__ and __LINE__ + 1 the method's source_location is this file and the line after the call; without them it is (eval at ...), line 1, which is what a backtrace will show you at three in the morning. Row 8: a block is a closure and sees factor; a string is compiled fresh in the class's scope and does not. Row 9: both evals return the block's or string's last value. Row 10: a proc called normally keeps its birthplace self (Object, the top-level object's class); instance_eval moves it. Row 11 is why class_eval exists at all: class needs a constant, so class klass is a SyntaxError, while klass.class_eval { def v } reopens whatever class the variable holds. Row 12: plain eval sees the current scope. Row 13: module_eval and class_eval are literally the same method.

Compared with Python

Python has no mechanism for changing what self means, because self is not a keyword: it is the first parameter of a function, and it is whatever you pass (row 2, row 10). So every row has a twin, but none of them switches anything. Reading a private variable is vars(safe)["_secret"] or simply safe._secret (row 1). The two def destinations of rows 3 and 4 become two explicit choices: exec a def into a namespace dictionary and setattr the function onto the class for an instance method, or wrap it in classmethod for a class method — with one asymmetry: a Python class method is reachable through an instance as well, while Ruby's Safe.new.y fails. Row 5, a method for one object, is types.MethodType(func, obj) stored on that object. Row 6: arguments need no instance_exec — they are parameters — and there is no strict/lenient split to trip on. Row 7: compile(src, "generated.py", "exec") gives generated code a filename for tracebacks, the same job as __FILE__/__LINE__; a bare exec(src) reports <string>. Row 8: eval sees the current scope by default and an explicit {} takes it away — the mirror of Ruby's block-versus-string split. Row 9 is the other structural fact: eval returns an expression's value, exec runs statements and returns None; Ruby's evals do both jobs and return the last value. Row 11 has a Python surprise of its own: class klass: is not an error — it creates a new class and binds the name klass to it, so the variable no longer refers to Safe. Row 13: eval and exec are two builtins, where module_eval and class_eval are one method under two names.

Verified output of instance_eval_and_class_eval_py.py — regenerated by tools/run_examples.py, never hand-typed.

 1. vars(safe)["_secret"] -- nothing to switch     42
 2. peek(safe) -- self is the argument             Safe
 3. exec("def x(self) ...") + setattr: Safe().x()  'instance x'
    Safe.x() -- no instance to be self             TypeError
 4. Safe.y = classmethod(...): Safe.y()            'class y'
    Safe().y() -- reachable from instances too     'class y'
 5. safe.only_me = MethodType(f, safe)             in vars(safe): ['only_me']
    hasattr(Safe(), "only_me")                     False
 6. add(safe, 3) -- self and args are parameters   45
    types.MethodType(add, safe)(3)                 45
    no strict/lenient split                        a function takes exactly its parameters
 7. compile(src, "generated.py", "exec")           co_filename = generated.py:1
    exec(src) -- no filename                       co_filename = <string>
 8. eval("factor * 2") -- sees the current scope   6
    eval("factor * 2", {}) -- an empty namespace   NameError
 9. eval("1 + 1") / exec("1 + 1")                  2 / None
10. peek(A()) / peek(safe) -- self is passed in    A / Safe
    a function has no self to move                 -
11. setattr(klass, 'v', ...): klass().v()          5
    class klass: pass -> klass is Safe             False
12. x = 5; eval("x + 1") -- the current scope      6
13. eval is exec -- two builtins, not aliases      False

The rule that -c runs a script and only the prompt shows an expression's value is the same expression/statement split as row 9: -c is not the prompt ↗ in the Python library.

Try it

  1. Give one Person a greet method with instance_eval and every Person a wave method with class_eval; use instance_exec to pass a suffix into a block that changes the person's @name. Print singleton_methods of the one, instance_methods(false) of the class, and respond_to?(:greet) from a second person.
  2. Write Module#def_from_string(name, body) that uses class_eval with a string and passes __FILE__ and __LINE__; define two methods with it and print instance_method(:name).source_location for each — then remove the file and line arguments and print again. Which one would you rather see in a backtrace?
Solution to 1

instance_eval_and_class_eval_kata_rb.rb in full — pasted here by tools/run_examples.py from the file CI runs.

# instance_eval_and_class_eval_kata_rb.rb — one method for one person, one for all of them.

class Person
  def initialize(name) = @name = name
end

ada = Person.new("Ada")
bob = Person.new("Bob")

ada.instance_eval do                                  # self is ada; def lands on ada's singleton class
  def greet = "Hello from #{@name}"
end

Person.class_eval do                                  # self is Person; def lands on Person
  def wave = "#{@name} waves"
end

suffix = "!"
ada.instance_exec(suffix) { |s| @name += s }          # arguments come through instance_exec

puts "1. ada.greet                       -> #{ada.greet.inspect}"
puts "2. bob.respond_to?(:greet)         -> #{bob.respond_to?(:greet)}"
puts "3. ada.singleton_methods           -> #{ada.singleton_methods.inspect}"
puts "4. bob.wave                        -> #{bob.wave.inspect}"
puts "5. Person.instance_methods(false)  -> #{Person.instance_methods(false).sort.inspect}"
puts "6. ada.instance_variable_get(:@name) -> #{ada.instance_variable_get(:@name).inspect}"

Verified output of instance_eval_and_class_eval_kata_rb.rb — regenerated by tools/run_examples.py, never hand-typed.

1. ada.greet                       -> "Hello from Ada!"
2. bob.respond_to?(:greet)         -> false
3. ada.singleton_methods           -> [:greet]
4. bob.wave                        -> "Bob waves"
5. Person.instance_methods(false)  -> [:wave]
6. ada.instance_variable_get(:@name) -> "Ada!"

See also