Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python and the self parameter

Tags:

python

I'm having some issues with the self parameter, and some seemingly inconsistent behavior in Python is annoying me, so I figure I better ask some people in the know. I have a class, Foo. This class will have a bunch of methods, m1, through mN. For some of these, I will use a standard definition, like in the case of m1 below. But for others, it's more convinient to just assign the method name directly, like I've done with m2 and m3.

import os

def myfun(x, y):
    return x + y

class Foo():
    def m1(self, y, z):
        return y + z + 42

    m2 = os.access
    m3 = myfun

f = Foo()
print f.m1(1, 2)
print f.m2("/", os.R_OK)
print f.m3(3, 4)

Now, I know that os.access does not take a self parameter (seemingly). And it still has no issues with this type of assignment. However, I cannot do the same for my own modules (imagine myfun defined off in mymodule.myfun). Running the above code yields the following output:

3
True
Traceback (most recent call last):
  File "foo.py", line 16, in <module>
    print f.m3(3, 4)
TypeError: myfun() takes exactly 2 arguments (3 given)

The problem is that, due to the framework I work in, I cannot avoid having a class Foo at least. But I'd like to avoid having my mymodule stuff in a dummy class. In order to do this, I need to do something ala

def m3(self,a1, a2):
    return mymodule.myfun(a1,a2)

Which is hugely redundant when you have like 20 of them. So, the question is, either how do I do this in a totally different and obviously much smarter way, or how can I make my own modules behave like the built-in ones, so it does not complain about receiving 1 argument too many.

like image 848
Svend Avatar asked Jan 21 '23 20:01

Svend


1 Answers

os.access() is a built-in function, in the sense that it's part of an extension module written in C. When the class is defined, Python doesn't recognize m2 as a method because it's the wrong type — methods are Python functions, not C functions. m3, however, is a Python function, so it's recognized as a method and handled as such.

In other words, it's m2 that's exceptional here, not m3.

One simple way to do what you want would be to make m3 a static method:

m3 = staticmethod(myfun)

Now the interpreter knows never to try and pass myfun() a self parameter when it's called as the m3 method of a Foo object.

like image 115
Luke Maurer Avatar answered Jan 30 '23 18:01

Luke Maurer