How to assign a list of instance methods to a class variable?
Question:
I have this class which works:
class Point:
def __init__(self):
self.checks = [self.check1, self.check2]
def check1(self):
return True
def check2(self):
return True
def run_all_checks(self):
for check in self.checks:
check()
The instance variable checks
is not specific to instances, so I want to move it to class level, here is my attempt :
class Point:
def __new__(cls, *args, **kwargs):
cls.checks = [cls.check1, cls.check2]
return super(Point, cls).__new__(cls, *args, **kwargs)
def check1(self):
return True
def check2(self):
return True
def run_all_checks(self):
for check in self.checks:
check()
The class definition seems
to work (in the sense that there are no syntax
errors), but when I run it, got error :
TypeError: Point.check1() missing 1 required positional argument: 'self'
Update
With @juanpa.arrivillaga’s solution, my problem is solved :
class ParentFuncs:
def check1(self):
print("check1")
def check2(self):
print("check2")
checks = [check1, check2]
def run_all_checks(self):
for check in self.checks:
check(self)
class ChildFuncs(ParentFuncs):
def check3(self):
print("check3")
def check4(self):
print("check4")
checks = ParentFuncs.checks + [check3, check4]
ChildFuncs().run_all_checks()
# Output
check1
check2
check3
check4
Answers:
Just do it in the class body, and then in run_all_checks
, make sure to pass the instance explicitly, because they will just be functions, not bound methods (which get created when accessing a method through and instance):
class Point:
def check1(self):
return True
def check2(self):
return False
checks = [check1, check2]
def run_all_checks(self):
for check in self.checks:
print(check(self))
point = Point()
point.run_all_checks()
Note, this doesn’t behave the same way in the case of inheritance. But that is probably OK, depending on your use-case.
You could do something like checks = ['check1', 'check2']
and then in run_all_checks
, something like getattr(self, check)()
, but IMO, this is more brittle. So I would go with your original approach in that case if I intended these methods to be overridden in subclasses.
I have this class which works:
class Point:
def __init__(self):
self.checks = [self.check1, self.check2]
def check1(self):
return True
def check2(self):
return True
def run_all_checks(self):
for check in self.checks:
check()
The instance variable checks
is not specific to instances, so I want to move it to class level, here is my attempt :
class Point:
def __new__(cls, *args, **kwargs):
cls.checks = [cls.check1, cls.check2]
return super(Point, cls).__new__(cls, *args, **kwargs)
def check1(self):
return True
def check2(self):
return True
def run_all_checks(self):
for check in self.checks:
check()
The class definition seems
to work (in the sense that there are no syntax
errors), but when I run it, got error :
TypeError: Point.check1() missing 1 required positional argument: 'self'
Update
With @juanpa.arrivillaga’s solution, my problem is solved :
class ParentFuncs:
def check1(self):
print("check1")
def check2(self):
print("check2")
checks = [check1, check2]
def run_all_checks(self):
for check in self.checks:
check(self)
class ChildFuncs(ParentFuncs):
def check3(self):
print("check3")
def check4(self):
print("check4")
checks = ParentFuncs.checks + [check3, check4]
ChildFuncs().run_all_checks()
# Output
check1
check2
check3
check4
Just do it in the class body, and then in run_all_checks
, make sure to pass the instance explicitly, because they will just be functions, not bound methods (which get created when accessing a method through and instance):
class Point:
def check1(self):
return True
def check2(self):
return False
checks = [check1, check2]
def run_all_checks(self):
for check in self.checks:
print(check(self))
point = Point()
point.run_all_checks()
Note, this doesn’t behave the same way in the case of inheritance. But that is probably OK, depending on your use-case.
You could do something like checks = ['check1', 'check2']
and then in run_all_checks
, something like getattr(self, check)()
, but IMO, this is more brittle. So I would go with your original approach in that case if I intended these methods to be overridden in subclasses.