5

I've read through the NetworkX tutorial and documentation, but was unable to find real world answers for this question.

Usually when using NetworkX, I might use strings to define nodes, then set several attributes.

e.g.

G = nx.Graph()
G.add_node('John Doe', haircolor = 'brown')
G.node['John Doe'][age] = 22

However, it seems like declaring a class with members instead of attributes is better in practice, especially when there are many attributes and readability might be an issue.

class Person:
     name = None
     age = None

Person p
p.name = 'John Doe'
p.age = 22
G.add_node(p)

Could someone be kind enough to validate my reasoning? I lack the foresight to see if Networkx node/edge attributes would be preferable.

1
  • This may sound like a strange question, but are you coming from a Java background? If so, you may be fighting the urge to 'class everything', whereas python is taking you down another route. The first example works because python deals with lists efficiently, and the use of dictionaries (think: a fancy list made to look like a key-store) is common. Notice that it took fewer lines of code in the first example - this is a good sign you are "being pythonic". Feb 21 '12 at 23:23
12

This doesn't answer your question. However. It seems necessary.

class Person:
     name = None
     age = None

Doesn't do what you're suggesting.

Those are two class-level attributes. They're emphatically not instance variables.

Also. You don't "declare" attributes at all. You don't declare them like that.

Person p isn't proper Python.

p= Person()
p.name = 'John Doe'
p.age = 22

This emphatically does not set the class level attributes created as part of the class. It creates additional instance-level attributes.

This may answer your question.

Networkx allows you to have any object associated with a node.

Feel free to do this

class Person( object ):
    def __init__( self, name, age ):
        self.name= name
        self.age= age

G.add_node('John Doe', data = Person( name='John Doe', age=22 ) )

Now you have all of your node data in a single object associated with the 'data' attribute.

For trivial name-value kinds of things, this is not obviously creating any real value.

But, if you have some node-specific method (rare in graph problems, but possible) then you'd have method functions associated with a node.

In graph theory problems, many of the algorithms work on the graph -- as a whole -- and you'll rarely find a use for a class with method functions.

Since the change is a trivial piece of syntax, it's probably simpler to start with

    G.add_node('John Doe', age=22 )

And migrate to

    G.add_node('John Doe', data = Person( name='John Doe', age=22 ) )

when you absolutely need to.

2
  • So if you did something like G.add_node(p); G.add_node(p); G.add_node(p) what about object p does networkx rely upon to make the last two calls effectively noops? Is it leaning on the __hash__ for p?
    – jxramos
    Apr 28 '21 at 19:41
  • Just came across this reference In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph. github.com/networkx/networkx/blob/…
    – jxramos
    Apr 28 '21 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.