Re: How do I extend a class that I never instantiate myself?

2015-10-11 Thread speeze . pearson
On Saturday, October 10, 2015 at 11:32:24 PM UTC-7, Chris Angelico wrote:
> If you REALLY want to look like Ruby, 

Ha! This thread has provided so many interesting monkey-patching techniques,
but this might be the most perverse. Very cute.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How do I extend a class that I never instantiate myself?

2015-10-11 Thread speeze . pearson
On Saturday, October 10, 2015 at 3:55:17 PM UTC-7, Steven D'Aprano wrote:
> # Solution 1: inject a new method into each and every instance in the tree.
> 
> node.foo = MethodType(foo, node)

Ooh, interesting. I'll meditate on that for a while.

> # Solution 2: hack the node type of each instance.
> 
> node.__class__ = MyNode

That is undoubtedly the coolest feature that I will absolutely never ever use.

> While both of the above have their uses, really the *right* way to do this
> is to stop being such an OOP purist. This isn't Java, we have functions for
> a reason.
> 
> Do you find len(alist) to be confusing and schizophrenic?

Um-- no, because I'm used to it. ;)
I'll definitely give the functional approach another think-over.

If I do go down the functional road, and I decide that I need to associate my
own data with each node (e.g. for callback functions), would there be a better
way to do that than just adding my own attribute onto each node?


> class MyNode(Node):
> @property
> def parent(self):
> parent = super(MyNode, self).parent
> if parent is not None:
> parent = MyNode(parent)
> return parent
> # etc.
> 
> Still a lot of work, and you really need to understand the original Node
> class very well. This is the problem with subclassing: it requires you to
> be intimately familiar with the *implementation details* of the class you
> subclass.

Hrm. Relying on implementation details of somebody else's library seems
dangerous... I think I'll shy away.

Thanks a lot!
-Spencer
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How do I extend a class that I never instantiate myself?

2015-10-11 Thread speeze . pearson
On Saturday, October 10, 2015 at 10:40:15 AM UTC-7, Ian wrote:
> name mangling

Awesome! I didn't know this was a feature.

> There's nothing wrong with [functional programming] IMO. In fact, Python
> does this in the standard library, e.g. len(objects) rather than
> objects.len().

...good point. I'll look at that option again with fresh eyes.

Thanks!
-- 
https://mail.python.org/mailman/listinfo/python-list


How do I extend a class that I never instantiate myself?

2015-10-10 Thread speeze . pearson
(This is a long post, but the question is simple. Most of this is
just me enumerating what I've already tried.)

Someone wrote a library that creates and manipulates `Node`s.
I would like to write another layer on top of this, to make
trees that behave just like the library's trees, but whose nodes
have some extra methods.

"Subclass!" is the classic OO answer, and my first instinct.
Problem: I never instantiate `Node` myself. `Node`s are created
somewhere deep inside the library, and there's no way to tell it
"don't use `Node`, use this class instead."

Does anyone know a programming pattern that solves this problem?

(That's it! That's the question. Everything after this is
descriptions of solutions I'm not happy enough with.)

"Write a wrapper!" is my next instinct. Basically,

  class MyNode(object):
...
def foo(self, *args, **kwargs):
  return self.node.foo(*args, **kwargs)
def bar(self, *args, **kwargs):
  return self.node.bar(*args, **kwargs)
...

This would be tedious, but acceptable, if I knew how to make
`MyNode.parent` and `MyNode.children` return `MyNode`s
instead of `Node`s. Every way I've thought of makes me cringe:
- Make `MyNode` maintain its own parent/child info, and keep it
  in lock-step with the underlying `Node`'s parent/child info.
  Objection: this is a lot of work, and just begging to get out of sync.
- Give every wrapped `Node` a `_wrapper` attribute, specifying
  the wrapping `MyNode` instance. Then `MyNode.children` would
  return `[child._wrapper for child in self._node.children]`.
  Objection: it just feels weird adding custom attributes to objects.
- Have a global registry mapping `Node`s to their corresponding
  `MyNode` wrappers. Then `MyNode.children` would return
  `[MyNode.wrappers[child] for child in self.node.children]`.
  Objection: I've been trained not to like global state.

My last idea is that my approach is *entirely* wrong: I shouldn't
be trying to make the tree's nodes instances of my own class --
I should just use the existing library's `Node` class, and write
my library in a functional style. Don't define `MyNode.foo()`,
instead define `mylibrary.foo(my_node)`.
I've got nothing against functional programming, but mixing it
so closely with OO would, I think, result in a confusing,
schizophrenic interface.

Last possibly relevant fact: the library I want to extend is
`xml.dom.minidom`. By `Node` I mean `Element`, and the specific
methods I want to add will modify attributes used for CSS/JavaScript.


Thank you very much!
-Spencer
-- 
https://mail.python.org/mailman/listinfo/python-list