Ruby的自我与Python的自我

时间:2011-07-12 22:07:21

标签: python ruby keyword self

  

可能重复:
  What is the difference between Ruby and Python versions of“self”?

Ruby和Python是类似的语言,它们在各种情况下都使用self关键字。 self在每种语言中的含义是什么,有什么区别?

3 个答案:

答案 0 :(得分:15)

Ruby和Python实际上是非常不同的语言(尽管它们确实有许多相似之处),即使Ruby的语法可以编写为类似Python(包含end关键词); - )

Ruby是基于消息的(它受SmallTalk-80的影响很大),“消息”被发送到对象。 Ruby支持给定范围的隐式接收器(明确称为self)。在Ruby中self 不是变量,而是一个计算当前对象上下文的表达式。

Python是基于属性的(因为我知道缺少一个更好的术语),因此更像是SELF和JavaScript,因为函数是直接执行的(而不是传递的消息)。 Python没有self关键字,只是self被用作方法的第一个参数的名称的惯例 - 这就是Python传递当前对象的方式上下文。

快乐的编码。

答案 1 :(得分:9)

在Python中,my_instance.a_method(an_argument)只是MyClass.a_method(my_instance, an_argument)的简写。因此MyClass.a_method的定义应该采用两个参数:

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

正如pst所说,使用变量名self只是一种惯例。你可以同样拥有

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

并且一切都会起作用......但不要这样做。

答案 2 :(得分:9)

关于Python我可以告诉你什么新内容。传统上,self作为方法的第一个参数传递,正如pst所说。来自Python docs

  

通常,方法的第一个参数称为self。这只不过是一个惯例:名称self对Python来说绝对没有特殊意义。但是请注意,如果不遵循惯例,您的代码可能对其他Python程序员来说可读性较低,并且可以想象可能会编写依赖于此类约定的类浏览器程序。

CRuby(或'MRI')虽然有类似的东西发生在引擎盖下。每个C扩展都可以使用

在Ruby类上定义(模块/类/单例)方法
  • rb_define_method(instance)
  • rb_define_singleton_method(singleton class)
  • rb_define_module_function(类/模块)

实际的实现函数总是将VALUE self作为它们的第一个参数,类似于Python习惯用法。在这些情况下,self指的是此特定邮件已发送到的对象实例,即如果您有

 person = Person.new
 person.do_sth

和do_sth碰巧在C中实现,然后会有相应的C函数

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

每个这样的实现都有来返回VALUE(Ruby对象的C表示),这与每个方法调用或消息发送(坚持Smalltalk用语)在Ruby中有一个返回值。 Ruby中没有void函数。

虽然我们需要在低级C代码中来回传递self,但您不需要在Ruby代码中这样做,Ruby会为您解决这个问题。 self的当前值存储在内部执行的当前线程上下文中,因此授予self的存在,消息“self”将始终评估为某个对象。

由于Ruby的动态特性,self引用的此对象的实际值随当前解释的代码的当前范围而变化。运行它来亲眼看看:

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

如果您想调用方法/从任何上下文向self发送消息,您可以明确地(例如self.method)或省略self作为接收者 - 那么,按照惯例,消息的隐式接收者将是self

一个有趣的旁注是Ruby对private方法的解释,这些方法不同,例如来自private的Java概念。 Ruby的私有方法只能通过使用self作为隐式接收者发送消息来调用,即

class A

  def a
    b
  end

  private

  def b
    puts "I'm private"
  end
end

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

有效,而用

代替方法a
def a
  self.b
end

会引发异常。这意味着Java中非常常见的东西

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

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

不适用于Ruby。愚蠢的例子,但只是为了说明一点:在Java中我们可以访问同一个类的其他实例的私有方法,这在Ruby中是不可能的,因为我们只能访问当前self的私有方法。

最后,为了使事情进一步复杂化,instance_evalclass_eval函数也会在执行期间改变self的值。