Python class methods: when is self not needed

前端 未结 4 467
别跟我提以往
别跟我提以往 2020-12-30 13:19

I\'m trying to rewrite some code using classes. At some point what I want is assign a member function a particular definition using a parameter value for each instance of an

4条回答
  •  暖寄归人
    2020-12-30 13:48

    You're using unbound method (nonLinearBipolarStep) in this code:

    activationFunctions = {
        'bipolar': nonLinearBipolarStep ,
    }
    

    Longer answer: methods are functions defined within class body and always take at least one argument, so called self (unless you use @staticfunction and turn them into normal functions). Self is an object of a given class, on which method is called (like this in C++). In python there's almost nothing special about this argument, it doesnt have to be named self. Now when you call unbound method, then first argument you've given will be interpreted as self and consumed. If you call bound methods, then this consumption doesnt happen (the method already has its self object). For example:

    class A:
      def foo(self, x): print(x)
    a = A()
    a.foo(1) # a.foo is bound method, a is self, prints 1
    A.foo(a, 2) # A.foo is unbound method, first argument becomes self, prints 2
    

    UPDATE: Why it works at all. Short answer: because dot (.) operator will update unbound method to bound when it can.

    Consider, what happens, when you write a.foo(1). First python check object a for foo and finds nothing (foo is not a value assigned to a). So it goes to a class (named A) and lo and behold - foo is there and is used. But here is a trick. Python will bind object a to unbound method A.foo (details escape me now, so imagine dragon did it) and make it into bound method. So a.foo is bound and doesnt need self anymore from arguments, thus 1 goes into argument x and everything works.

    Now to your code: you use 'bipolar': nonLinearBipolarStep in map, which is unbound method. Then in constructor (init) you set self.run to value returned from _getActivation, which is taken from activationFunctions map. In given example you return nonLinearBipolarStep unbound method and assign it to self.run. Now you call ag.run. Going by the logic from the previous paragraph ag.run is first looked inside ag object. And here is your error - its found. As python found ag.run value inside ag object, it never consulted ag type (Activation) for run object and never had a chance to bind it. So ag.run is unbound method and expect self argument as first.

    You've in general two options. Either do ag.run(ag, 4), which will work, but its ugly, or manually bind method to self in constructor. The latter you can do like this:

    self.run = self._getActivation(func).__get__(self)
    

提交回复
热议问题