Cratobi
Cratobi

Reputation: 11

Is it possible to init a class and call a method at the same time?

Today I was solving a university problem. There was this class call which I can not change. This was the code:

n = some_class.some_method('arg_1', 'arg_2')

So my written class code is this:

class some_class:
  def __init__(self, arg_1, arg_2):
    self.some_method(arg_1, arg_2)

  def some_method(self, arg_1, arg_2):
    self.arg_1 = arg_1
    self.arg_2 = arg_2

However, I am getting this error:

AttributeError: 'str' object has no attribute 'arg_1'

Examining a bit, I found that some_method's self is not referring to its own class and thinking it's an argument. So is there any way to init the class inside the method? I can not init the class before this line "n = some_class.some_method('arg_1', 'arg_2')".

EDIT:

I directly implemented the sudo code according to one solution however now I got this error: TypeError: some_method() missing 1 required positional argument: 'arg_2'

class Some_class:
  def __init__(self, arg_1, arg_2):
    self.some_method(arg_1, arg_2)

  @staticmethod
  def some_method(self, arg_1, arg_2):
    self.arg_1 = arg_1
    self.arg_2 = arg_2


  def __str__(self):
    return 'YES'

n = Some_class.some_method('arg_1', 'arg_2')

Upvotes: 0

Views: 1614

Answers (2)

mimetist
mimetist

Reputation: 171

There are a few misunderstandings on how your code works.

Classes have two kinds of methods: static and non-static methods.

Non-Static methods: These are the usual methods that you define inside a class. They always have the same first argument: "self"

This "self" argument always refers to the current instance of the class (i.e. They only work on instances).

Static methods: These methods do not have a "self" argument because they do not work on instances. It is like instances do not exist for them.

There are many uses for these kind of methods, but a simple way to look at them is as set of utils stored in a class.

Now, going back to your code.

class Some_class:
  def __init__(self, arg_1, arg_2):
    self.some_method(arg_1, arg_2)

  @staticmethod
  def some_method(self, arg_1, arg_2):
    self.arg_1 = arg_1
    self.arg_2 = arg_2

  def __str__(self):
    return 'YES'

n = Some_class.some_method('arg_1', 'arg_2')

That fails because "some_method" requires 3 arguments (even though the first one is "self" it does not refers to an instance, because for a static method instances do not exist). This means that you must remove any "self" reference in the arguments or in the body.

So, that's why your code didn't work.

Now, what can you do instead? Use classmethod instead of staticmethod:

class Some_class:
  def __init__(self, arg_1, arg_2):
    self.arg1 = arg_1
    self.arg2 = arg_2

  @classmethod
  def some_method(self_class, arg_1, arg_2):
    return self_class(arg_1, arg_2)

  def __str__(self):
    return 'YES'

n = Some_class.some_method('arg_1', 'arg_2')

I named "self_class" the first argument of "some_method" in order to make it clear that that first argument is not a reference to an instance (even though you could name it "self" as usual).

The fisrt argument of classmethod methods is a reference to the class.

Upvotes: 0

Thomas Weller
Thomas Weller

Reputation: 59302

To make the call like this, some_method must be static. That's because some_class is missing the braces () which would instantiate an object. Static methods do not have a self argument and have a @staticmethod attribute.

If that method shall return an instance, you need to call the constructor some_class().

class some_class:
    def __init__(self, arg_1, arg_2):
        self.arg_1 = arg_1
        self.arg_2 = arg_2

    @staticmethod
    def some_method(arg_1, arg_2):
        return some_class(arg_1, arg_2)


some_object = some_class.some_method('arg_1', 'arg_2')
print(some_object)

Style note: classes should be upper case in Python.

Upvotes: 4

Related Questions