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]