Python and self parameter

I am having some problems with the self parameter, and some seemingly inconsistent behavior in Python annoy me, so I find it better to ask some people in the know. I have a class, Foo . This class will have a bunch of m1 methods, via mN . For some of them, I will use the standard definition, as in the case of m1 below. But for others, itโ€™s more convenient to simply assign the method name directly, as I did 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 accept the self parameter (apparently). And it still has no problems with this type of destination. However, I cannot do the same for my own modules (imagine myfun in mymodule.myfun ). Executing the above code gives 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, because of the framework in which I work, I cannot escape at least the Foo class. But I would like to avoid using my mymodule material in a dummy class. To do this, I need to do something ala

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

This is very redundant when you have 20 of them. So the question is how can I do this in a completely different and obviously much smarter way, or how can I make my own modules behave as built-in ones, so he doesn't complain that he gets too much of one argument.

+4
source share
5 answers

I just want to add that the behavior does not contradict, as already hinted at Luke.

Just try the following

 print Foo.__dict__ {'__doc__': None, '__module__': '__main__', 'm1': <function m1 at 0x02861630>, 'm2': <built-in function access>, 'm3': <function myfun at 0x028616F0>} 

Here you can see that Python cannot distinguish between m1 and m2. Therefore, both methods are evaluated using the associated method.

A related method is something like a method with an additional first argument pointing to an object: self.m(1, 2) -> m(self, 1, 2)

This binding behavior is implemented only for custom methods. This explains why self.m2("/", os.R_OK) not evaluated as m2(self, "/", os.R_OK) .

Last demo:

 print Foo.m1 <unbound method Foo.m1> print Foo.m2 <built-in function access> print f.m1 <bound method Foo.m1 of <__main__.Foo instance at 0x02324418>> print f.m2 <built-in function access> 

Further information on the various types of functions can be found here:

http://docs.python.org/reference/datamodel.html

And, as mentioned earlier, this binding mechanism can also be prevented using the staticmethod handle:

http://docs.python.org/library/functions.html#staticmethod

+2
source

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

In other words, this m2 is exceptional here, not m3 .

One easy way to do what you want is to make a static m3 method:

 m3 = staticmethod(myfun) 

Now the interpreter does not know to try to pass the parameter myfun() a self when it called the m3 method of the Foo object.

+4
source

I think you are looking for staticmethod (). See Docs here .

 m2 = staticmethod(os.access) m3 = staticmethod(myfun) 

As for why m2 worked in your example and m3 did not, I donโ€™t understand this. Printing f.m2 and f.m3 in your original example shows that f.m2 is a direct reference to the os.access built-in function, while f.m3 is a related method (bound to an instance of f).

+2
source

In this case, you should use the staticmethod function. When writing static methods of a class, you can use it as a decorator:

 class A: def printValue(self,value): print value @staticmethod def staticPrintValue(value): print value >>> A.printValue(5) Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> A.printValue(5) TypeError: unbound method printValue() must be called with A instance as first argument (got int instance instead) >>> A.staticPrintValue(5) 5 
+1
source

One way would be to manually apply the static method decorator:

 class Foo(object): m3 = staticmethod(mymodule.myfun) 
0
source

Source: https://habr.com/ru/post/1333866/


All Articles