1

I have a python object that has various attrs, one of them is check=None.

class MenuItem:
    check: bool = True

During the __init__() process, it parses it's own attrs and looks if they are callable. If so, it calls the function, and replaces it's instance variable with the result of the function:

    def __init__(self):
        self.request = ...
        if callable(self.check):
            self.check = self.check(self.request)

The purpose is to have subclasses that may replace class attrs by lambda functions:

class MainMenuItem(MenuItem):
    check = lambda request: request.user.is_authenticated

So far, so good. But as the calling of instance methods implicitly adds self as first parameter, I would have to write every lambda (or external function) as lambda self, request: ... - external functions must be def check_superuser(self, request): ... - which IMHO looks bad.

Is there a way in Python to call a function from a method "as staticmethod"? Like

if callable(self.check):
    self.check = staticmethod(self.check)(self.request)

(this obviously doesn't work)

Any hint's welcome. Do I completely think wrong?

cards
  • 3,936
  • 1
  • 7
  • 25
nerdoc
  • 1,044
  • 10
  • 28
  • Does this help: https://stackoverflow.com/questions/3849576/how-to-call-a-static-method-of-a-class-using-method-name-and-class-name – JuanIsFree Nov 21 '22 at 20:33
  • 1
    Are you maybe looking for an impedance matcher, which discards 1st arg (`self`) when dispatching to the "real" lambda function? Also, consider using named functions instead of lambdas. For one thing, you can `@decorate` them. – J_H Nov 21 '22 at 20:43
  • in which part of `MenuItem` the `check` variable becomes callable? – cards Nov 21 '22 at 21:52
  • @JuanIsFree, no, I can't declare the attribute as staticmethod in the first place. @cards: in my real code too, it "becomes" callable at declaration time of inherited classes. It's indeed a MenuItem, and eg AdminMenu declares `check=lambda request: request.user.is_superuser`. @J_H: this is way to complicated for this approach. Meanwhile @Antony Hatchkins has answered it already - this is what I sought. Thanks all. – nerdoc Nov 22 '22 at 20:34

1 Answers1

2

Is this what you are looking for?

class A:
    check: bool = True
    def __init__(self):
        self.request = 'request'
        if callable(self.check):
            self.check = self.__class__.check(self.request)

class B(A):
    check = lambda request: len(request)

b = B()
print(b.check)

outputs 7

Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
  • Thanks. I always tried to fix it with type(self).check(self.request). But obviously this is calling the Metaclass' check method - which is kind of the same, but it did not work properly. Thanks a bunch. – nerdoc Nov 22 '22 at 20:30