0

I want store a function in a class, then call it later. Values can be called via the instance or class, but the not functions. Here's the demo:

def my_fn(a, b):
  print(a, b)

class Foo(object):
  fn = my_fn
  avar = 5

  def later(self):
    # Called as class variable works.
    print(Foo.avar)
    # Called as class variable works.
    Foo.fn('hello', 'world')

  def later2(self):
    # Called as class variable works.
    print(Foo.avar)
    # Called via self doesn't work.
    self.fn('hello', 'world')


f = Foo()

f.later()
# 5
# hello world

f.later2()
# 5
# self.fn('hello', 'world')
# TypeError: my_fn() takes 2 positional arguments but 3 were given

The error means that it was successful in accessing both the variable and function when called by class in later(): Foo.avar and Foo.fn. But when called via the instance in later2, self.avar succeeded but self.fn failed because it was given an extra argument, presumably 'self'.

Is this simply an inconsistency due to the way Python inserts self into method calls, or is there a way to call functions stored in class variables through an instance?

CodeGuy2001
  • 147
  • 1
  • 8
  • 1
    `__init__` will be called with `self` when you create the instance — it needs to be in the signature. Why aren't you just saving `self.later = fn` in `__init__(self, fn)`? It's not clear what you are trying to achieve with the indirection of a second function. – Mark Aug 01 '19 at 01:08
  • `later` doesn't take any parameters, but you're calling it with 2 arguments. Conversely, `self.fn()` takes 2 parameters, but you don't provide any arguments. Are you expecting the `hello` and `world` arguments to be passed through magically? – Barmar Aug 01 '19 at 01:10
  • @MarkMeyer Won't that have the same problem of implicitly passing `self` when you call `self.later()`? – Barmar Aug 01 '19 at 01:11
  • Yes to the above. I corrected the code/output... – CodeGuy2001 Aug 01 '19 at 01:13
  • @Barmar no, it's not a bound function. `f = Foo(my_fn); f.later('hello', 'world')` works as expected. – Mark Aug 01 '19 at 01:13
  • https://stackoverflow.com/questions/12882317/why-always-add-self-as-first-argument-to-class-methods – Manvir Aug 01 '19 at 01:14
  • You're missing `self` as the first argument to `later`. When I add that, your code works as expected. – Barmar Aug 01 '19 at 01:15
  • Barmar, you're right. Thanks! – CodeGuy2001 Aug 01 '19 at 01:19
  • I've re-edited the question and updated the code to illustrate the problem. PTAL. – CodeGuy2001 Aug 01 '19 at 15:50

0 Answers0