2

This could be a so called XY problem, so let me start with what I want:

ed = Edit.add(1).add(2).add(3)
print(ed.op)    # [1,2,3]

Following is what I tried and basically I got working code, but I'm not sure if I did it right or if there are other options.

The first add(1) is a class method call and the following add(2) and add(3) are instance method calls. I started here:

class Edit:
    def __init__(self):
        self.op = []

    @classmethod
    def add(cls, x): 
        self = cls()
        return self.add_im(x)

    def add_im(self, x): # im = instance method
        self.op.append(x)
        return self

ed = Edit.add(1).add_im(2).add_im(3)
print(ed.op)

but I wanted the same name everywhere, so I added some attribute name rewriting:

class Edit:
    def __init__(self):
        self.op = []

    def __getattribute__(self, name):
        if name == "add":
            name = "add_im"
        return super().__getattribute__(name)

    @classmethod
    def add(cls, x): 
        self = cls()
        return self.add(x)

    # im = instance method
    def add_im(self, x): 
        self.op.append(x)
        return self

ed = Edit.add(1).add(2).add(3)
print(ed.op)

UPDATE:

as @lllrnr101 noted in the comments, one part of my question has been answered here: Same name for classmethod and instancemethod

My question is broader, I think it does not have to be closed as a duplicate.

UPDATE2:

After studying the mentioned thread I have now new version I am satisfied with:

class dualmethod(classmethod):
    def __get__(self, instance, typ):
        if instance is None:
            instance = typ()  # create an instance "on the fly"
        return self.__func__.__get__(instance, typ)

class Edit:
    def __init__(self):
        self.op = []

    @dualmethod
    def add(self, x): 
        self.op.append(x)
        return self

ed = Edit.add(1).add(2).add(3)
print(ed.op)    # [1,2,3]
11
  • Do you want to forward class method to instance method? Commented Apr 10, 2021 at 6:52
  • use descriptor? Commented Apr 10, 2021 at 6:54
  • Why not Edit.get_object().add().add().add()? Commented Apr 10, 2021 at 6:56
  • @tstanisl I'm sorry, not sure what you mean Commented Apr 10, 2021 at 6:57
  • 2
    Okay, so I still have the question of why not just write ed = Edit().add(1).mul(10). Alternately, if you really want to save typing and/or make it look cleverer or more elegant, you could make top-level factory functions for the first operation: e.g. def add(x): return Edit().add(x). Commented Apr 10, 2021 at 7:58

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.