-3

Classes, methods, and instances have me thoroughly confused. Why is it that this works:

class Computer:
    
    def config(self):
        print('i5, 16gb, 1TB')

com1 = Computer()
com1.config()

But this does not?:

class Computer:
    
    def config(self):
        print('i5, 16gb, 1TB')

com1 = Computer()
Computer.config()

But, if you modify the code directly above to include the instance as an argument when calling the method, like so:

Computer.config(com1)

it works? I see the difference between the two, but I don't understand it.

syrrious
  • 7
  • 1
  • Actually `instance.method()` does a call to `class.method(instance)` in the background. (That behaviour might be modified by decorators.) – Klaus D. Jul 01 '20 at 18:53
  • `com1` is an instance of the class `Computer`. They are not interchangeable. – chepner Jul 01 '20 at 18:56
  • This question already has answers here:[TypeError: Missing one required positional argument](https://stackoverflow.com/a/50594457/7414759) – stovfl Jul 01 '20 at 20:25

3 Answers3

0

In your example Computer.config is an instance method, means it is bound to an object, or in other words requires an object. Therefore in your second example you would write:

com1.config()

You can also write it in the following style:

Computer.config(com1)

which is the same and just syntactic sugar. In same special cases you might prefer the latter one, e.g. when duck typing is required, but the first one is definitely the preferred way.

In addition, there are staticmethod or classmethod functions, which don't require any objects. An example would be this:

class Computer
    @staticmethod
    def config():
        print("Foo")

Computer.config()  # no object required at all, because its a staticmethod

Please notice the missing self reference. Technically Computer.config as a staticmethod is just a simple function, but it helps to group functionalities so to make them a class member.

Daniel Stephens
  • 2,371
  • 8
  • 34
  • 86
  • I'm still a bit confused. If `Computer.config` is bound to an object, making it an instance method, then what is `com1.config()` if not an instance method? And what makes one an instance method? I thought that an instance of a class was just the creation of the object? Sorry, I'm just finding it hard to understand. – syrrious Jul 01 '20 at 19:15
  • No classifier at all around a method makes it **always** an instance method which requires an object. ONLY `staticmethod` and `classmethod` make them non-bound methods which are often used as convinience functions for certain tasks – Daniel Stephens Jul 02 '20 at 03:21
  • To sum it up, `com1.config()` OR `Computer.config(com1)` is exactly the same, but first is preferred and means instance method. Only my last method shows you how to make a non-instance method – Daniel Stephens Jul 02 '20 at 03:22
0

This is because config() is an instance method, and not a static method. An instance method, simply said, is shared across all objects of a class, and cannot be accessed by just using the class name. If you want to call config() by just using class name, you have to tell compiler that it is static. To do this use @staticmethod tag, and remove the self argument:

 class Computer:
    @staticmethod
    def config():
        print('i5, 16gb, 1TB')

com1 = Computer()
com1.config()

And as you said:

if you modify the code directly above to include the instance as an argument when calling the method, like so:

This is because, every instance function takes self as it's first argument. Basically self is somewhat similar to this in C++ or Java, and it tells which object to work upon, i.e., self acts as a pointer to the current object. When you passed the com1 object to the argument, it took self for com1.

That means that when you invoke com1.config() what you are actually doing is calling config with com1 as its argument. So com1.config(() is the same as Computer.config(com1).

Shivam Jha
  • 3,160
  • 3
  • 22
  • 36
-1

Why doesn't the second approach work?

Because Computer is an instance of something called a meta-class. It is somewhat the class definition and not actually an instance of Computer. com1 is an instance created by Computer. You can use com1 to invoke its non-static functions but you can't use the meta-class Computer to invoke non-static functions, which need an object to be ran on.

Why does the third approach work?

Have you noticed the self in the definition of the config function? That means that when you invoke com1.config() what you are actually doing is calling config with com1 as its argument. So com1.config() is the same as Computer.config(com1).

PouyaH
  • 31
  • 7
  • `Computer` is a **class**, not a metaclass. A metaclass is something else. – khelwood Jul 01 '20 at 18:58
  • @khelwood `Computer`, when used as an object, is an instance of a meta-class. It is a class but an instance of meta-class. The second code uses `Computer` like an instance so it behaves like an instance of a meta-class. – PouyaH Jul 01 '20 at 19:03
  • If you think it's important to explain how classes are instances of metaclasses, OK, but it's pretty irrelevant to the question. But your answer still says "the meta-class Computer" instead of "the *class* Computer". – khelwood Jul 01 '20 at 20:41