Welcome, guest | Sign In | My Account | Store | Cart

graph_tool library is based on boost C++ library and provides Vertex class binding for Python. If we wanted to extend this Vertex class and add some attributes and methods, it wouldn't let us do that due to private constructor in C++ code (RuntimeError: This class cannot be instantiated from Python). We can overcome this obstacle using Proxy pattern.

In the __getattr__ method, if the attribute(or function name) is not in the Subclass MyVertex, then it looks for attributes of Vertex object that is defined inside MyVertex.

Python, 23 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from graph_tool.all import Vertex, Graph

class MyVertex:
    def __init__(self, g):
        self.g = g
        self.v = g.add_vertex()
        self.halted = False
        
    def vote_for_halt(self):
        self.halted = True

    def __getattr__(self, attr):
        return getattr(self.v, attr)

if __name__ == "__main__":        
    g = Graph()
    v1 = MyVertex(g)
    v2 = MyVertex(g)
    g.add_edge(v1, v2)
    v1.vote_for_halt()
    print v1.out_degree()  # will print 1
    print v1.halted  # will print True
    print v1.foo  # will raise error: AttributeError: 'Vertex' object has no attribute 'foo'

2 comments

Martin Miller 10 years, 9 months ago  # | flag

The __getattr__() object method is only called for attributes that are not found in the "usual places", according Python 2's documentation. This means that the if/else clause in your MyVertex version isn't necessary and the code for the whole method could be reduce to simply:

def __getattr__(self, attr):
    return getattr(self.v, attr)
Ahmet Emre Aladağ (author) 10 years, 9 months ago  # | flag

Thank you, I didn't know that! I'm fixing it.