[Tutor] help with refactoring needed -- which approach is more Pythonic?

Brian van den Broek bvande at po-box.mcgill.ca
Sat Feb 12 10:56:37 CET 2005


Kent Johnson said unto the world upon 2005-02-11 11:34:
> Brian van den Broek wrote:
> 
>> Alan Gauld said unto the world upon 2005-02-10 02:58:
>>
>>> Pseudo code:
>>>        class Body:
>>>           def __init__(self,content):
>>>             self.contents = contents
>>>             self.nodes = []
>>>
>>>           def parse(self):
>>>              for line in self.contents:
>>>                  if line == NodeStartTag:
>>>                     node = Node()
>>>                  if line == NodeEndTag:
>>>                     self.nodes.append(node)
>>>                  node.append(line)
>>>
>>>        class Node:
>>>          def __init__(self,lines=[]):
>>>               self.lines = lines
>>>          def append(self,item):
>>>               self.lines.append(item)
>>>          def parse(self):
>>>               # your parsing method here.
>>
>>
>>
>> Hi all,
>>
>> YAQ (Yet Another Question):
>>
>> Following the general pattern, I end up with a Body object which has 
>> an attribute .nodes that consists of a list of Node objects.
>>
>> So, something like:
>>
>> My Example Body
>>    Node List
>>       Node the first
>>       Node the second
>>
>> Is there any way to make methods of the Node class access attributes 
>> of `parents' of instances? I would like a Node instance such as Node 
>> the first above to be aware just what it is a node of and what its 
>> siblings are.
> 
> 
> You have to tell it the parent. ("Explicit is better than implicit.") 
> For example you could pass a reference to Body to the Node in the 
> constructor:
> 
>            def parse(self):
>               for line in self.contents:
>                   if line == NodeStartTag:
>                      node = Node(self)    # HERE
>                   if line == NodeEndTag:
>                      self.nodes.append(node)
>                   node.append(line)
> 
> In general I think this is a bad design. I try to avoid telling 
> components about their parents in any kind of containment hierarchy. If 
> the component knows about its parent, then the component can't be reused 
> in a different context and it can't be tested without creating the 
> expected context.
> 
> Is there another way you could accomplish what you want?
> 
> Kent

Hi,

thanks to everyone for responding. It hadn't occurred to me I could 
pass self to a class instantiation. So, that solves my issue given my 
original design intent: thanks.

As for Kent's question: I may have a better way now. I'd appreciate 
help deciding. So, if I may, I'll say a bit more about the problem 
domain. I've made the description as short as I know how.

The file format I am working with is from a `folding notebook' style 
of application (<www.treepad.com> if anyone is interested). It's a 
2-pane editor/outliner. There is a tree of nodes with each with a (not 
necessarily unique) title, a unique id number, other metadata and an 
associated article (in plain text, html, or RTF [ugh!]). The file 
format also defines a header for the entire file.

I have a class TP_file, which, when instantiated, creates an Head 
object and, for each node, a Node object.

The program supports hyperlinks in the article text, both to other 
nodes (by unique id) and to external objects. Before posting this most 
recent question, I'd planed for the Node class to have a method that 
would scan the node's article, looking for text strings that match any 
node title and linkifying them. (I already know how to deal with 
already linkified instances of the string and cases where one string 
is the title of multiple nodes.) Since this method needs to know the 
titles of all Node objects, I thought I needed to make each Node aware 
of its TP_file object to fetch its nodes. (Hence my most recent 
question.) And, since it alters the article text of a Node, I thought 
it needed to be a method of the Node class.

But, while reflecting on Kent's question and thinking of how to 
describe my problem domain, I think I have a better idea now :-)

It still seems to me that the actual updating of the article should be 
a Node method (it is the Node object's article that is being updated, 
after all). Call it node_linkify. The new thought is to create two new 
methods for the TP_file class:

- One to build a dictionary with Node titles as keys and
   a list of the corresponding unique ids as values.

- Another to pass that list into a the node_linkify Node method,
   once for each Node object of the TP_file.

Does this seem like a reasonable approach given my description of the 
problem?

Thanks for the continued help -- it is most appreciated. I might just 
become an OOP programmer yet! ;-)

Best to all,

Brian vdB




More information about the Tutor mailing list