How to pass arguments to python function whose first parameter is self?
Asked Answered
S

5

6

Take the following simplified example.

class A(object):
    variable_A = 1
    variable_B = 2

    def functionA(self, param):
        print(param+self.variable_A)

print(A.functionA(3))

In the above example, I get the following error

Traceback (most recent call last):
  File "python", line 8, in <module>
TypeError: functionA() missing 1 required positional argument: 'param'

But, if I remove the self, in the function declaration, I am not able to access the variables variable_A and variable_B in the class, and I get the following error

Traceback (most recent call last):
  File "python", line 8, in <module>
  File "python", line 6, in functionA
NameError: name 'self' is not defined

So, how do I access the class variables and not get the param error here? I am using Python 3 FYI.

Sanmicheli answered 30/1, 2017 at 11:51 Comment(1)
A is a class. You need A() (instance of A).Preform
D
12

You must first create an instance of the class A

class A(object):
    variable_A = 1
    variable_B = 2

    def functionA(self, param):
        return (param+self.variable_A)


a = A()
print(a.functionA(3))

You can use staticmethod decorator if you don't want to use an instance. Static methods are a special case of methods. Sometimes, you'll write code that belongs to a class, but that doesn't use the object itself at all.

class A(object):
    variable_A = 1
    variable_B = 2

    @staticmethod
    def functionA(param):
        return (param+A.variable_A)

print(A.functionA(3))

Another option is to use classmethod decorator. Class methods are methods that are not bound to an object, but to a class!

class A(object):
    variable_A = 1
    variable_B = 2

    @classmethod
    def functionA(cls,param):
        return (param+cls.variable_A)

print(A.functionA(3))
Dogbane answered 30/1, 2017 at 11:59 Comment(2)
You could have used a classmethod tooShayneshays
This is a technically correct answer but it doesn't explain anything...Shayneshays
H
2

functionA in your snippet above is an instance method. You do not pass "self" directly to it. Instead, you need to create an instance in order to use it. The "self" argument of the function is, in fact, the instance it's called on. E.g.:

a = A()
a.functionA(3)

P.S. Note that your functionA calls print but doesn't return anything, meaning it implicitly returns None. You should either have it return a value and print it from the caller, or, as I have done above, call it and let it print on its own.

Hazlip answered 30/1, 2017 at 11:54 Comment(3)
O that was easy. Thanks for the explanation. Can u also tell me why it was able to call the function without creating an object? Did it act as a static function or something?Sanmicheli
A function "that takes self as its first argument" (=> whose first argument is named "self") is a just a function whose first argument happens to be named "self". That doesn't make it an instance method. What makes it an instance method is being an attribute of a class an looked up on an instance of this class. Read this : wiki.python.org/moin/FromFunctionToMethod for more about the inners.Shayneshays
@brunodesthuilliers arg, that was extremely badly worded, I agree. I'll try to edit and rectify this.Hazlip
C
1

Create an object of A first.

a = A()
a.functionA(3)
Chatelain answered 30/1, 2017 at 11:53 Comment(0)
S
1

When a function object (what the def statement creates) is an attribute of a class AND is looked up (using the obj.attrname scheme) on the class or an instance of the class, it gets turned into a method object. This method object is itself a callable. If the lookup happens on an instance, this instance will be "magically" inserted as the first argument to the function. If not, you will have to provide it by yourself (just like you would for any other argument).

You can read more about this (and how the "magic" happens here: https://wiki.python.org/moin/FromFunctionToMethod

In your case, you lookup the function on the class, so it expects two arguments (self and param), but you only pass param, hence the error.

You defined variable_A and variable_B as class attributes (attributes that will be shared between all instances of the class). If that's really the intention, and you want a method you can call on the class itself and that will be able to access class attributes, you can make functionA a classmethod (it works the same as an "instance" method except it's the class that is 'magically' inserted as first argument):

class A(object):
  variable_A = 1
  variable_B = 2

  @classmethod
  def functionA(cls, param):
    return param + cls.variable_A

Then you can call functionA either directly on the class itself:

print(A.functionA(42))

or on an instance if you already have one at hand:

a = A()

# ...

print(a.functionA(42))

Now if you really wanted variable_A and variable_B to be per-instance attributes (each instance of A has it's own distinct variables), you need to 1/ create those attributes on the instance itself in the initialier method and 2/ call functionA on some A instance, ie:

class A(object):
    def __init__(self, variable_A=1, variable_B=2):
        self.variable_A = variableA
        self.variable_B = variableB

  def functionA(self, param):
    return param + self.variable_A



a1 = A() # using default values
print(a1.functionA(42))

a2 = A(5) # custom value for variable_A
print(a2.functionA(42))
Shayneshays answered 30/1, 2017 at 12:11 Comment(0)
M
0
class A(object):
    variable_A = 1
    variable_B = 2

    def functionA(self, param):
        print(param+self.variable_A)

A().functionA(3)

A() is calling the class to create an instance

4

[Program finished]

You can use return in function and then print at last. Posting this answer as per OP template , accepted answers and other answers are recommended way to do it.

Maxine answered 15/5, 2021 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.