Compare the following code in C++:
#include <iostream>
#include <vector>
struct A
{
virtual void bar(void) { std::cout << "one" << std::endl; }
};
struct B : public A
{
virtual void bar(void) { std::cout << "two" << std::endl; }
};
void test(std::vector<A*> objs, void (A::*fun)())
{
for (auto o = objs.begin(); o != objs.end(); ++o)
{
A* obj = (*o);
(obj->*fun)();
}
}
int main()
{
std::vector<A*> objs = {new A(), new B()};
test(objs, &A::bar);
}
and in Python:
class A:
def bar(self):
print("one")
class B(A):
def bar(self):
print("two")
def test(objs, fun):
for o in objs:
fun(o)
objs = [A(), B()]
test(objs, A.bar)
The C++ code will print:
one
two
while the Python code will print
one
one
How can I pass "a pointer to a method" and resolve it to the overridden one, achieving the same behavior in Python as in C++?
To add some context and explain why I initially thought about this pattern. I have a tree consisting of nodes that can be subclassed. I would like to create a generic graph traversal function which takes a node of the graph as well as a function which might be overridden in subclasses of graph nodes. The function calculates some value for a node, given values calculated for adjacent nodes. The goal is to return a value calculated for the given node (which requires traversing the whole graph).
Regarding your edit, one thing you could do is use a little wrapper lambda that calls the method you want to reference. This way the method call looks like "regular python code" instead of being something complicated based on string-based access.
In your example, the only part that would need to change is the call to the test
function:
test(objs, (lambda x: x.bar()))
The following produces the output you want:
class A:
def bar(self):
print("one")
class B(A):
def bar(self):
print("two")
def test(objs, funcname):
noop = lambda: None
for o in objs:
getattr(o, funcname, noop)()
objs = [A(), B()]
test(objs, "bar")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With