0

I'm still quite new at python, and I've looked in a book I got and searched here and on the web. But I'm not getting an answer that is down to the level I apparently can grasp atm.

I got 2 different class's.

main.py

import listManipulator as lm

lc = lm.listManipulator()

li = [some list]
li2 = [some other list]

li = lm.listManipulator.cleanupList(li) # This call method does not requires the method to have the self argument
li2 = lc.cleanupList(li2) # This call method requires the method to have the self argument

So I'm trying to call my cleanup method, and I'm getting confused by this self argument, yet again. I'ved figured out there are 2 ways calling the method as shown above.

listManipulator.py
class listManipulator:

        def cleanupList(self, list):
              *do stuff*
              return list

As you can tell from the comments in the code, in one of the calls, I NEED the target method to have the self argument, but I don't in the other. Can anyone give me a down to earth explanation of why the frack this is?

Morten Paaske
  • 35
  • 1
  • 1
  • 6
  • Why do you think that one does not require the self argument and the other does? – mkrieger1 Apr 23 '23 at 16:27
  • If you call a method on an instance of a class, that instance is automatically provided as the first parameter to the call (traditionally called `self`). If you call a method on the class itself, no instance is provided (indeed, there is no instance that even could be provided in that case). – jasonharper Apr 23 '23 at 16:27
  • @mkrieger1 what I've come up with so fare is that `_lm.listManipulater.cleanup..._` "provides" the instance of the class, and fore some reason, that negates the need for the _self_ argument. And the `_lc.cleanup..._` points to an already instantiated instance of the class, which for some reason makes it need the _self_ argument. @jasonharper I kind of get what your saying, but I'm still quite confused.. :/ Calling on the class it self is where I need the _self_ argument? – Morten Paaske Apr 23 '23 at 17:06
  • TL;DR: If you're calling the function *on the class*, not on an instance, then there is no `self` which gets automatically passed (because there's no instance which _could_ get passed). If you're calling the method on an instance, then it *does* get a `self` argument passed implicitly. For more info, read the two duplicates linked above. – deceze Apr 23 '23 at 17:08
  • @deceze Am I getting this right, using __lm.listManipulater.cleanup....__ there is no instantiated instance and therefor no instance "__self__" there to get passed, therefor the method has no need for the argument? – Morten Paaske Apr 23 '23 at 18:01
  • “No need” is a weird way of putting it. You decide whether the method has “a need” for `self` when writing it. That also determines how you want to call the method later. The error here is that you’re calling it two different inconsistent ways. – deceze Apr 23 '23 at 18:23
  • @deceze okay, it's not that I want to call it in different ways, it's more a case of trying to get a grasp on the differences and when to use which. Not knowing what is "best practices". I'm kind of thinking it should be a static method, since the class won't take any attributes. – Morten Paaske Apr 23 '23 at 19:05
  • Yes, instance methods which accept a `self` are the standard case, as that's what you want 95% of the time. If you have special cases like static methods or class methods, that's where you'd use the `@staticmethod` or `@classmethod` decorators explicitly. – deceze Apr 23 '23 at 19:08

1 Answers1

0

Python Classes can have different types of functions, what you are describing are class and static methods.

A class method requieres a class instance with a self variable:

class MyClass:
    def __init__(self, value):
        self.value = value
 
    def get_value(self):
        return self.value

# Create an instance of MyClass
obj = MyClass(10)
 
# Call the get_value method on the instance
print(obj.get_value())  # Output: 10

But theres also a static method that does not require the class instance and you create it by decorading it with a @staticmethod decorator:

class MyClass:
    def __init__(self, value):
        self.value = value

    @staticmethod
    def get_max_value(x, y):
        return max(x, y)

# Create an instance of MyClass
obj = MyClass(10)

print(MyClass.get_max_value(20, 30)) # Output: 30

print(obj.get_max_value(20, 30)) # Output: 30
Andrey
  • 68
  • 2
  • 9