82

Yet another question on what the 'self' is for, what happens if you don't use 'self' and what's 'cls' for. I "have done my homework", I just want to make sure I got it all.

self - To access an attribute of an object, you need to prefix the attribute name with the object name (objname.attributename). The same way self is used to access an attribute inside the object (class) itself. So if you didn't prefix a variable with self in a class method, you wouldn't be able to access that variable in other methods of the class, or outside of the class. So you could omit it if you wanted to make the variable local to that method only. The same way if you had a method and you didn't have any variable you wanted to share with other methods, you could omit the self from the method arguments.

cls - Each instance creates it's own "copy" of the attributes, so if you wanted all the instances of a class to share the same variable, you would prefix that variable name with 'cls' in the class declaration.

Is this all right? Thanks.

Max Segal
  • 1,955
  • 1
  • 24
  • 53
Joelmc
  • 873
  • 2
  • 8
  • 5
  • 1
    See also: [What is the 'cls' variable used in python classes?](http://stackoverflow.com/questions/4613000/what-is-the-cls-variable-used-in-python-classes) – HostileFork says dont trust SE Nov 14 '12 at 18:33
  • Does this answer your question? [Difference between 'cls' and 'self' in Python classes?](https://stackoverflow.com/questions/4613000/difference-between-cls-and-self-in-python-classes) – dank8 Oct 29 '22 at 12:46

2 Answers2

123

The same way self is used to access an attribute inside the object (class) itself.

Not inside the object / class, just inside the class' instance methods. self is just a convention, you could call it whatever you wanted, even something different in each method.

So if you didn't prefix a variable with self in a class method, you wouldn't be able to access that variable in other methods of the class, or outside of the class.

self is used in instance methods, cls is often used in class methods. Otherwise, correct.

So you could omit it if you wanted to make the variable local to that method only.

Yes, inside a method a variable name is like inside any other function -- the interpreter looks for the name locally, then in closures, then in the globals / module level, then in the Python built-ins.

The same way if you had a method and you didn't have any variable you wanted to share with other methods, you could omit the self from the method arguments.

No, you can't just omit "self" from the method arguments. You have to tell Python you want a staticmethod, which won't automatically get passed the instance of the class, ether by doing @staticmethod above the def line, or mymethod = staticmethod(mymethod) below the method body.

Each instance creates it's own "copy" of the attributes, so if you wanted all the instances of a class to share the same variable, you would prefix that variable name with 'cls' in the class declaration.

Inside the class definition, but outside any methods, names are bound to the class -- that's how you define methods etc. You don't prefix them with cls or anything else.

cls is generally used in the __new__ special staticmethod, or in classmethods, which you make similarly to staticmethods. These are methods that only need access to the class, but not to things specific to each instance of the class.

Inside a classmethod, yes, you'd use this to refer to attributes you wanted all instances of the class, and the class itself, to share.

Like self, cls is just a convention, and you could call it whatever you wanted.

A brief example:

class Foo(object):

    # you couldn't use self. or cls. out here, they wouldn't mean anything

    # this is a class attribute
    thing = 'athing'

    def __init__(self, bar):
        # I want other methods called on this instance of Foo
        # to have access to bar, so I create an attribute of self
        # pointing to it
        self.bar = bar

    @staticmethod
    def default_foo():
        # static methods are often used as alternate constructors,
        # since they don't need access to any part of the class
        # if the method doesn't have anything at all to do with the class
        # just use a module level function
        return Foo('baz')

    @classmethod
    def two_things(cls):
        # can access class attributes, like thing
        # but not instance attributes, like bar
        print cls.thing, cls.thing
agf
  • 171,228
  • 44
  • 289
  • 238
  • 3
    If you really want to understand this kind of stuff, and you've already gone through a Python tutorial or two, and read the docs on `classmethod`, `staticmethod`, etc., then read the [Python Data Model](http://docs.python.org/reference/datamodel.html) reference page. – agf Sep 26 '11 at 12:21
  • Hm,so use static method if you dont want it to be accessed by the instances and dont want it to access other methods and use class methods if you want it to be shared between class instances? – Joelmc Sep 26 '11 at 12:45
  • 1
    "Don't want it to be accessed by the instances" No, the instances can still access the static method, just like you can from outside the class, it just can't access the other methods on the instance, or it's attributes. Anything you can do in a static method you could just do in a normal function outside of the class -- just make it a static method if you want to make it clear it's related to the rest of the class. Use a class method if it doesn't need to access things that are special to the instance -- `bar` in the example above. When you're just learning, stick with normal instance methods. – agf Sep 26 '11 at 13:01
17

You use self as the first argument in regular methods where the instance is passed automatically through this argument. So whatever the first argument is in a method - it points to the current instance

When a method is decorated with @classmethod it gets the class passed as its first argument so the most common name for it is cls as it points to the class.

You usually do not prefix any variables (hungarian notation is bad).


Here's an example:

class Test(object):
    def hello(self):
        print 'instance %r says hello' % self
    @classmethod
    def greet(cls):
        print 'class %r greet you' % cls

Output:

>>> Test().hello()
instance <__main__.Test object at 0x1f19650> says hello

>>> Test.greet()
class <class '__main__.Test'> greet you
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • 5
    Hungarian notation isn't bad. It's fiendish. – Fred Foo Sep 26 '11 at 12:06
  • By prefixing I meant "self.myvariable". Sorry, but I don't think this answers my question, at least all of them, if I don't get it. – Joelmc Sep 26 '11 at 12:15
  • 5
    I think I'll get into the habit of downvoting answers that make absolute and unargumented claims. There are two types of Hungarian notation; read more here: http://www.joelonsoftware.com/articles/Wrong.html – Paul Manta Sep 26 '11 at 12:20