Differencebetween Ruby and Python Versions Of"Self"

What is the difference between Ruby and Python versions ofself?

Python is designed to support more than just object-oriented programming. Preserving the same interface between methods and functions lets the two styles interoperate more cleanly.

Ruby was built from the ground up to be object-oriented. Even the literals are objects (evaluate 1.class and you get Fixnum). The language was built such that self is a reserved keyword that returns the current instance wherever you are.

If you're inside an instance method of one of your class, self is a reference to said instance.

If you're in the definition of the class itself (not in a method), self is the class itself:

class C
puts "I am a #{self}"
def instance_method
puts 'instance_method'
end
def self.class_method
puts 'class_method'
end
end

At class definition time, 'I am a C' will be printed.

The straight 'def' defines an instance method, whereas the 'def self.xxx' defines a class method.

c=C.new

c.instance_method
#=> instance_method
C.class_method
#=> class_method

Ruby's self vs. Python's 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.

What does Ruby have that Python doesn't, and vice versa?

You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

An example:

class Kaka
puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.

Python vs. Ruby for metaprogramming

There's not really a huge difference between python and ruby at least at an ideological level. For the most part, they're just different flavors of the same thing. Thus, I would recommend seeing which one matches your programming style more.

ruby should I use self. or @

When you use @lines, you are accessing the instance variable itself. self.lines actually goes through the lines method of the class; likewise, self.lines = x goes through the lines= method. So use @ when you want to access the variable directly, and self. when you want to access via the method.

To directly answer your question, normally you want to set the instance variables directly in your initialize method, but it depends on your use-case.

What difference has adding the self keyword made?

[Edit]

It is likely that the original section of the tutorial was just plain wrong. Omitting the "self" receiver causes the methods to assign a value to the method local variable "current_user" with no other effect.

My original answer below is incorrect and should be ignored (because writer methods foo=(x) cannot be called without a receiver, as can other methods).

[Incorrect Original Answer Below]

The reason for using the "self" receiver is likely for clarity.

If "self" is omitted then, to the untrained eye, it looks like you are simply assigning the "user" variable to a new variable named "current_user" with no other effect. Experienced Rubyists know that if there is a method named "current_user" on the object instance then it will be called instead of just creating and assigning a new variable but this detail can easily be overlooked, especially if the method is inherited or otherwise not declared in the current class definition section.

By using the "self" keyword explicitly you are clearly stating that you are calling a method on this object instance.

python: what's the difference between pythonbrew and virtualenv?

Pythonbrew is akin to Ruby's rvm: It's a shell function that allows you to:

  • Build one or more complete self-contained versions of Python, each stored locally
    under your home directory. You can build multiple versions of Python this way.
  • Switch between the versions of Python easily.

The Pythons you build are completely isolated from each other, and from whatever version(s) of Python are installed system-wide.

Virtualenv is similar, but not quite the same. It creates a Python virtual environment that, conceptually, sits on top of some existing Python installation (usually the system-wide one, but not always). By default, on Unix platforms (and the Mac), it creates symbolic links to the various Python library modules, so you're literally sharing those modules with the "real" underlying Python implementation. But, virtualenv has its own "bin" directory and "site-packages" directory. Anything extra you install in the Python virtual environment is only available within that environment.

One advantage to Pythonbrew is that the Python environments it creates are truly, and completely, self-contained. They cannot be contaminated by anything that gets screwed up in an underlying base Python install, because there isn't an underlying base install. This is not true of virtualenv environments. If you create a virtualenv Python, and then you somehow screw up the base Python instance it sits above (e.g., accidentally deleting part of the base Python's "site" directory while logged in as root), you'll screw up any virtualenv environment based on that Python, too.

However, virtualenv has its own advantages. Probably the biggest advantage is that it is lightweight. Since Pythonbrew compiles Python from scratch, to create one of its environments, creating a Pythonbrew Python environment takes some time. By comparison, creating a virtualenv Python environment is really fast.

You can, in fact, use them together. Here's one situation where you might want to do that.

  • Your base system uses Python 2.6.
  • You need to install Python 2.7.
  • For whatever reason, you can't (or don't want to) install Python 2.7 system wide,
    side-by-side with Python 2.6.

In such a case, you could use Pythonbrew to install a base Python 2.7 under your home directory, where it doesn't conflict with anything installed elsewhere. Then, you can create one or more lightweight virtualenv Python environments that are based on your Pythonbrew-installed 2.7 Python. For instance, you could use virtualenv to spin up short-lived test environments for Python 2.7 that way.

I doubt most people actually do that. (I don't.) But there's no reason you can't.

Instance variable: self vs @

Writing @age directly accesses the instance variable @age. Writing self.age tells the object to send itself the message age, which will usually return the instance variable @age — but could do any number of other things depending on how the age method is implemented in a given subclass. For example, you might have a MiddleAgedSocialite class that always reports its age 10 years younger than it actually is. Or more practically, a PersistentPerson class might lazily read that data from a persistent store, cache all its persistent data in a hash.

Is there any difference between `def self.myMethod` and `def myMethod`?

def self.method_name will define a class method rather than an instance method - as will

class << self; def foo; end; end

A good post on the topic is this post from Yehuda Katz

for example:

class Foo
def method_1
"called from instance"
end

def self.method_2
"called from class"
end

class << self
def method_3
"also called from class"
end
end
end

> Foo.method_1
NoMethodError: undefined method 'method_1' for Foo:Class

> Foo.method_2
=> "called from class"

> Foo.method_3
=> "also called from class"

> f = Foo.new
=> #<Foo:0x10dfe3a40>

> f.method_1
=> "called from instance"

> f.method_2
NoMethodError: undefined method 'method_2' for #<Foo:0x10dfe3a40>

> f.method_3
NoMethodError: undefined method 'method_3' for #<Foo:0x10dfe3a40>

Difference between Python self and Java this

About self in Python (here is the source: Python self explanation):

The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self is the convention, and people will generally frown at you when you use something else.) self is not special to the code, it's just another object.

Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self..

About this in Java being explained by Oracle (here is the source: Java this explanation):

Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.
The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.



Related Topics



Leave a reply



Submit