开发者

Ruby's self vs. Python's self [duplicate]

This question already has answers here: Closed 11 years ago.

Possible Duplicate:

What is the difference between Ruby and Python versions of“self”?

Ruby and Python are similar languages that both have a self keyword used开发者_如何学C in various situations. What does self mean in each language, and what are the differences?


Ruby and Python are actually very different languages (although they do share many similarities) even if Ruby has a syntax that can be written to look like Python (with the inclusion of end keywords) ;-)

Ruby is message-based (it was heavily influenced by SmallTalk-80) and "messages" are sent to objects. Ruby supports an implicit receiver (explicitly known as self) for a given scope. In Ruby self is not a variable, but rather an expression that evaluates to the current object context.

Python is property-based (for lack of a better term I know) and is thus more similar to SELF and JavaScript as functions are executed directly (instead of messages being passed). Python has no self keyword and it is merely convention that self is used as the name of the first parameter of a method -- which is how Python passes around the current object context.

Happy coding.


Regarding Python I can tell you nothing new. The self there is passed conventionally as the first parameter of a method, as pst said. From Python docs

Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers, and it is also conceivable that a class browser program might be written that relies upon such a convention.

CRuby (or 'MRI') has something similar which happens under the hood though. Every C extension may define (module/class/singleton) methods on a Ruby class by using

  • rb_define_method (instance)
  • rb_define_singleton_method (singleton class)
  • rb_define_module_function (class/module)

The actual implementing functions always take VALUE self as their first argument, in analogy to the Python idiom. self in these cases refers to the object instance this particular message has been sent to, i.e. if you have

 person = Person.new
 person.do_sth

and do_sth would happen to be implemented in C, then there would be a corresponding C function

VALUE
person_do_sth(VALUE self) {
    //do something
    return self;
}

Every such implementation has to return a VALUE (the C representation of a Ruby object), which relates to the fact that every method call or message sent (to stick to Smalltalk parlance) has a return value in Ruby. There is no such thing as a void function in Ruby.

Although we need to pass self back and forth in the low-level C code, you don't need to do so in Ruby code, Ruby takes care of this for you. The current value of self is stored internally in the current thread context that is executed, so the existence of self is granted, the message "self" will always evaluate to some object.

Due to the dynamic nature of Ruby, the actual value of of this object being referenced by self changes with the current scope of the code that is currently interpreted. Run this to see for yourself:

puts "#{self} - declared in global scope"  # the 'top self' aka 'main'
class << self
  puts "#{self} - 'main's singleton class" # main's singleton or 'eigenclass'
end

puts "Starting to interpret class A code"

class A
  puts "#{self} - When do I get executed!?" # self is class A

  class << self
    puts "#{self} - And me!?" # now A's  singleton class
    def a # declaring method in class's singleton class results in class method
      puts "#{self} - declared in singleton class" # it's A
    end 
  end

  def self.b
    puts "#{self} - declared in class method" # self is class A again -> class method
    class << self
      puts "#{self} - declared in Class A's singleton class" # now it's Class A's singleton class
    end
  end

  def c
    puts "#{self} - declared in instance method" # self is instance of A
    class << self
      puts "#{self} - declared in instance's singleton class" # now it's the A instance's singleton class
    end
  end

end  

puts "All so far has happened simply by interpreting A's code" 

a = A.new
A.a
A.b
a.c

If you want to call a method/send a message from any context to self, you could do this either explicitly (e.g. self.method) or you omit self as the receiver - then, by convention, the implicit receiver of the message will be self.

An interesting side note to this is Ruby's interpretation of private methods, which differs e.g. from the Java notion of private. Ruby's private methods are only callable by sending a message using self as an implicit receiver, i.e.

class A

  def a
    b
  end

  private

  def b
    puts "I'm private"
  end
end

a = A.new
a.a # => I'm private

works, whereas replacing method a by

def a
  self.b
end

would raise an exception. This implies that something very common in Java

class A {
    private boolean compareUs(A a1, A a2) { ... }

    public boolean equals(A a1, A a2) {
        return (a1.compareUs() == a2.compareUs());
    }
}

won't work in Ruby. Silly example, but just to illustrate the point: In Java we can access private methods of other instances of the same class, this would not be possible in Ruby because we can only access private methods of the current self.

Finally, to complicate things a bit further, the instance_eval and class_eval functions will also alter the value of self during execution.


In Python, my_instance.a_method(an_argument) is just shorthand for MyClass.a_method(my_instance, an_argument). Thus the definition of MyClass.a_method should take two parameters:

class MyClass(object):
    def a_method(self, an_argument):
        print self   # self (the instance) is available in the method

As pst said, the use of the variable name self is just a convention. You could equally have

class MyClass(object):
    def a_method(this_instance, an_argument):
        print this_instance

and everything would work the same...but don't do that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜