Ruby 的自我与 Python 的自我

发布于 2024-11-19 17:56:31 字数 321 浏览 3 评论 0原文

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

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

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 in various situations. What does self mean in each language, and what are the differences?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

像极了他 2024-11-26 17:56:32

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

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

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

快乐编码。

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.

独孤求败 2024-11-26 17:56:32

关于Python,我不能告诉你什么新东西。正如 pst 所说,self 按照惯例作为方法的第一个参数传递。来自 Python 文档

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

CRuby(或“MRI”)在幕后也有类似的事情发生。每个 C 扩展都可以使用

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

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

 person = Person.new
 person.do_sth

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

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

每个这样的实现 < em>必须返回一个VALUE(Ruby对象的C表示),这与每个方法调用或发送的消息(以粘住以 Smalltalk 的说法)的返回值是红宝石。 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 方法的解释,它不同于 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

有效,而替换方法 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 的值。

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.

Bonjour°[大白 2024-11-26 17:56:32

在 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

,一切都会一样......但不要这样做。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文