Ruby的自我与Python的自我

jrd*_*oko 10 ruby python self keyword

可能重复:
Ruby和Python版本的"self"有什么区别?

Ruby和Python是类似的语言,它们都有self在不同情况下使用的关键字.这是什么self意思每种语言,以及有什么区别?

小智 15

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

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

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

快乐的编码.


mat*_*ray 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
Run Code Online (Sandbox Code Playgroud)

正如pst所说,使用变量名self只是一种惯例.你也可以

class MyClass(object):
    def a_method(this_instance, an_argument):
        print this_instance
Run Code Online (Sandbox Code Playgroud)

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


emb*_*oss 9

关于Python我可以告诉你什么新东西.的self存在通常传递作为方法的第一个参数,作为所述PST.来自Python文档

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

CRuby(或'MRI')有类似的东西,但在引擎盖下发生.每个C扩展都可以使用Ruby类定义(模块/类/单例)方法

  • rb_define_method(实例)
  • rb_define_singleton_method(单例类)
  • rb_define_module_function(类/模块)

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

 person = Person.new
 person.do_sth
Run Code Online (Sandbox Code Playgroud)

并且do_sth碰巧在C中实现,那么就会有相应的C函数

VALUE
person_do_sth(VALUE self) {
    //do something
    return self;
}
Run Code Online (Sandbox Code Playgroud)

每个这样的实现必须返回一个VALUE(Ruby对象的C表示),这与发送的每个方法调用或消息(坚持Smalltalk用语)在Ruby中具有返回值有关.voidRuby中没有函数这样的东西.

虽然我们需要self在低级C代码中来回传递,但您不需要在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
Run Code Online (Sandbox Code Playgroud)

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

一个有趣的旁注是Ruby对private方法的解释,它与Java的概念不同private.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
Run Code Online (Sandbox Code Playgroud)

工作,而替换方法a

def a
  self.b
end
Run Code Online (Sandbox Code Playgroud)

会引发例外.这意味着Java中非常常见

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

    public boolean equals(A a1, A a2) {
        return (a1.compareUs() == a2.compareUs());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

最后,为了进一步复杂化instance_eval,class_eval函数和函数也会改变self执行期间的值.