【发布时间】:2011-07-12 22:07:21
【问题描述】:
可能重复:
What is the difference between Ruby and Python versions of“self”?
Ruby 和 Python 是相似的语言,它们都有一个self 关键字,用于各种情况。 self 在每种语言中是什么意思,有什么区别?
【问题讨论】:
-
Python 没有
self关键字。它只是按惯例使用。
可能重复:
What is the difference between Ruby and Python versions of“self”?
Ruby 和 Python 是相似的语言,它们都有一个self 关键字,用于各种情况。 self 在每种语言中是什么意思,有什么区别?
【问题讨论】:
self 关键字。它只是按惯例使用。
Ruby 和 Python 实际上是非常不同的语言(尽管它们确实有很多相似之处),即使 Ruby 的语法可以写成看起来像 Python(包含 end 关键字) ;-)
Ruby 是基于消息的(它深受 SmallTalk-80 的影响)并且“消息”被发送到对象。 Ruby 支持给定范围的隐式接收器(明确称为self)。在 Ruby 中,self 不是一个变量,而是一个计算当前对象上下文的表达式。
Python 是基于属性的(因为我知道没有更好的术语),因此更类似于 SELF 和 JavaScript,因为函数是直接执行的(而不是传递消息)。 Python 没有 self 关键字,只是约定 self 用作方法的第一个参数的名称——这就是 Python 绕过当前对象上下文的方式。 p>
编码愉快。
【讨论】:
关于 Python,我不能告诉你什么新鲜事。正如 pst 所说,self 通常作为方法的第一个参数传递。来自Python docs
通常,方法的第一个参数称为 self。这只不过是一个约定:名称 self 对 Python 绝对没有特殊含义。但是请注意,如果不遵循约定,您的代码对其他 Python 程序员的可读性可能会降低,并且还可以想象编写依赖于这种约定的类浏览器程序。
CRuby(或“MRI”)有类似的事情发生在引擎盖下。每个 C 扩展都可以通过使用在 Ruby 类上定义(模块/类/单例)方法
实际的实现函数总是以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_eval 和 class_eval 函数也会在执行期间改变 self 的值。
【讨论】:
在 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
一切都一样……但不要那样做。
【讨论】: