-1

I am new to Python with Java background, the concept of "self" in function confuses me. I understand first argument "self" mean the object itself, but I do not understand how Python make this work. I also know that I could use "this" or "that" or "somethingElse", and Python would still understanding I mean to use the object.

I copied some code from a reddit post:

class A():
    def __init__(self):
        self.value = ""

    def b(this):
        this.value = "b"

    def c(that):
        that.value = "c"

a = A()
print(a.value)

a.b()
print(a.value)
>>>"b"
a.c()
print(a.value)
>>>"c"

How do python knows I do not mean to use an object here in the first argument? For example I modified the above code a bit:

class A():
    def __init__(self):
        self.value = ""

    def b(this):
        this.value = "b"

    def c(that):
        that.value = "c"

    def somethingElse(someObjectIWantToPass):
        someObjectIWantToPass.value = "still referring A.value"

class B():
    def __init__(self):
        self.value = ""
a = A()
print(a.value)

a.b()
print(a.value)

a.c()
print(a.value)

a.somethingElse()

print(a.value)

b = B()

a.somethingElse(b)

print (b.value)

And it broke:

b
c
still referring A.value
Traceback (most recent call last):
  File "D:/Documents/test.py", line 32, in <module>
    a.somethingElse(b)
TypeError: somethingElse() takes 1 positional argument but 2 were given
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
lamwaiman1988
  • 3,729
  • 15
  • 55
  • 87
  • 1
    *“How do python knows I do not mean to use an object here in the first argument?”* It doesn’t know what you mean. If you *mean* to pass some arbitrary object to `A.somethingElse`, `a.somethingElse(b)` is simply incorrect. If you wanted a method operating on the class, you would use the `@classmethod` decorator, accept `(cls, someObjectIWantToPass)` as parameters, and call `A.somethingElse(b)`. – Ry- Apr 13 '18 at 03:08
  • Related / maybe a dup: [What is the purpose of self](https://stackoverflow.com/questions/2709821/what-is-the-purpose-of-self) – miradulo Apr 13 '18 at 03:09
  • Because the first argument for instance methods is always the instance itself, your `someObjectIWantToPass` becomes `self` in this case. You should rewrite it to read `def somethingElse(self, someObjectIWantToPass):`. – Selcuk Apr 13 '18 at 03:15
  • Use `self`, `this`,`that`, `theOther`, `george`, `bob` or `delores` - it doesn't matter. The first argument is the object, *regardless* of what you call it :-) – paxdiablo Apr 13 '18 at 03:40

2 Answers2

6

A method's first argument is always1 its instance. Calling it self is idiomatic in Python but that name is strictly convention.

class A():
    def some_method(me):  # not called `self`
        print(str(id(me))

a = A()
a.some_method()
print(id(a))

If you're trying to pass another arbitrary object in, it has to be the second argument.

class B():
    def another_method(self, other):
        print(id(other))

b = B()
b.another_method(a)
print(id(b))  # different!
print(id(a))  # the same.

1 Not actually always. @classmethod decorated methods use cls as their first argument, and @staticmethod` decorated methods have nothing passed to its first argument by default.

class C():
    @classmethod
    def some_classmethod(cls, other, arguments):
        # first argument is not the instance, but
        # the class C itself.

    @staticmethod
    def something_related(other, arguments):
        # the first argument gets neither the instance
        # nor the class.
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
1

You are too focused on syntactic sugar. Just realize that the first parameter in a non static member function in python is the reference to the current object. Whether you want to call it this, that, foobar, poop, it doesn't matter. The first parameter of a member function is considered the reference to the object on which the method is called.

The use of self is just a universal way everyone has understood it and the way Python recommends - a convention if you may.

The same goes for **kwargs and *args. These are simply conventions that have permeated the Python ecosystem and everyone just uses it that way, but it doesn't mean you can't give them a different name.


Your last example broke because the function you are calling (A.something) does not take any parameters. This will make sense if you understood what I had said earlier about first parameter in non static member function being a reference to the object on which the method was called.

smac89
  • 39,374
  • 15
  • 132
  • 179