Changing self: if self is a tree how to set to a different self

Discussion in 'Python' started by Bart Kastermans, Jul 10, 2008.

  1. I am playing with some trees. In one of the procedures I wrote
    for this I am trying to change self to a different tree. A tree
    here has four members (val/type/left/right). I found that self = SS
    does not work; I have to write self.val = SS.val and the same for
    the other members (as shown below). Is there a better way to do this?

    In the below self is part of a parse tree, F is the parse tree of a
    function f with argument x. If a node in the parse tree is labelled
    f, we should replace it by the parse tree for the function f, F, with
    the remainder of the tree substituted for the input variable for the
    function f, here x.

    def elimF (self):
    if self.val == "f":
    SS = F.copy ()
    SS.subst ('x', self.left)
    self.val = SS.val # from here: set self to be SS
    self.type = SS.type
    self.left = SS.left
    self.right = SS.right # completed: set self to be SS

    if self.left != None: # iterate onward, inf recursion if f
    # appears. Would need a check in
    # real version
    self.left.elimF ()
    if self.right != None:
    self.right.elimF ()

    Best,
    Bart
    Bart Kastermans, Jul 10, 2008
    #1
    1. Advertising

  2. Bart Kastermans

    Terry Reedy Guest

    Bart Kastermans wrote:
    > I am playing with some trees. In one of the procedures I wrote
    > for this I am trying to change self to a different tree. A tree
    > here has four members (val/type/left/right). I found that self = SS
    > does not work; I have to write self.val = SS.val and the same for
    > the other members (as shown below). Is there a better way to do this?
    >
    > In the below self is part of a parse tree, F is the parse tree of a
    > function f with argument x. If a node in the parse tree is labelled
    > f, we should replace it by the parse tree for the function f, F, with
    > the remainder of the tree substituted for the input variable for the
    > function f, here x.
    >
    > def elimF (self):
    > if self.val == "f":
    > SS = F.copy ()
    > SS.subst ('x', self.left)
    > self.val = SS.val # from here: set self to be SS
    > self.type = SS.type
    > self.left = SS.left
    > self.right = SS.right # completed: set self to be SS


    If you examine nodes from their parent, I believe you can do the
    substitution in one step. Something like:

    for slot,child in ( ('left',self.left), ('right',self.right) ):
    if child is not None:
    if child.val == 'f':
    setattr(self, slot, F.copy().subst('x', child.left))
    child.elimF

    where .subst returns the modified tree.

    >
    > if self.left != None: # iterate onward, inf recursion if f
    > # appears. Would need a check in
    > # real version
    > self.left.elimF ()
    > if self.right != None:
    > self.right.elimF ()


    Terry Jan Reedy
    Terry Reedy, Jul 10, 2008
    #2
    1. Advertising

  3. Terry Reedy <> writes:

    > Bart Kastermans wrote:
    >> I am playing with some trees. In one of the procedures I wrote
    >> for this I am trying to change self to a different tree. A tree
    >> here has four members (val/type/left/right). I found that self = SS
    >> does not work; I have to write self.val = SS.val and the same for
    >> the other members (as shown below). Is there a better way to do this?
    >>
    >> In the below self is part of a parse tree, F is the parse tree of a
    >> function f with argument x. If a node in the parse tree is labelled
    >> f, we should replace it by the parse tree for the function f, F, with
    >> the remainder of the tree substituted for the input variable for the
    >> function f, here x.
    >>
    >> def elimF (self):
    >> if self.val == "f":
    >> SS = F.copy ()
    >> SS.subst ('x', self.left)
    >> self.val = SS.val # from here: set self to be SS
    >> self.type = SS.type
    >> self.left = SS.left
    >> self.right = SS.right # completed: set self to be SS

    >
    > If you examine nodes from their parent, I believe you can do the
    > substitution in one step. Something like:
    >
    > for slot,child in ( ('left',self.left), ('right',self.right) ):
    > if child is not None:
    > if child.val == 'f':
    > setattr(self, slot, F.copy().subst('x', child.left))
    > child.elimF
    >
    > where .subst returns the modified tree.


    That worked very well. The option that looks even better to me was
    just to build a copy (the exceptional case of the root of the tree
    that is needed bugged me a bit). Then self does not have to be
    changed at all. Your use of setattr made me find getattr, and this
    allowed for a quite smooth (I think) implementation.

    def elimF (self):
    """ do the substitution of all nodes labelled f.

    """
    if self.val == "f":
    ret_val = F.subst ('x', self.left)
    ret_val.left = NoneOr (ret_val.left, 'elimF')
    ret_val.right = NoneOr (ret_val.right, 'elimF')
    return ret_val
    else:
    return Tree (self.val, self.type, \
    NoneOr (self.left, 'elimF'), \
    NoneOr (self.right, 'elimF') )

    This uses the function:

    def NoneOr (tree, mem_function, *arguments):
    """ if tree is not None then tree.mem_function (arguments). """
    if tree == None:
    return None
    else:
    return getattr (tree, mem_function) (*arguments)



    Bart
    Bart Kastermans, Jul 12, 2008
    #3
  4. Bart Kastermans

    Paul McGuire Guest

    On Jul 12, 6:18 am, Bart Kastermans <kaste...@bart-kastermanss-
    macbook.local> wrote:
    > This uses the function:
    >
    > def NoneOr (tree, mem_function, *arguments):
    >     """ if tree is not None then tree.mem_function (arguments). """
    >     if tree == None:
    >         return None
    >     else:
    >         return getattr (tree, mem_function) (*arguments)
    >
    > Bart


    <persnickety>
    This code reads wrongly to me on a couple of levels. First, I think
    the general computing consensus is that if-then-else is more readable/
    logical if you assert the positive condition for the then-part, and
    put the alternative condition in the else-part. My impression is that
    the non-None-ness of tree is actually the positive assertion, as in:

    if tree != None:
    return getattr(tree, mem_function)(*arguments)
    else:
    return None

    Next, the more Pythonic test for None-ness is most clearly written as:

    if tree is not None:

    as there is only one None, and the identity "is not" check is simpler/
    faster for Python to execute (and possibly - and more importantly -
    also simpler for readers to follow, as this reads more like a
    continuous sentence instead of a mixture of prose and mathematical
    notations).

    One might even suggest you could further abbreviate this test to:

    if tree:

    and get the same behavior. I would quibble with that, however, that
    this merely exploits a side-effect of Python, in which None values are
    always False, and *most* non-None values are True. But Python also
    interprets many non-None values as False, such as 0, or empty
    containers, such as lists, tuples, dicts, and strings. In fact, your
    tree class sounds like a structured container to me, and it would be
    reasonable to assume that you might implement __nonzero__ (pre-Python
    2.6) or __bool__ (Python 2.6 and later) in your class to return False
    for an empty tree, which would still be a valid and not-None tree.
    You should be able to invoke methods on an empty tree just as one can
    call "".upper(). So for this case, I would stick with the more
    explicit "if tree is not None".

    Another Pythonicity is that methods will *always* return a value, even
    if you do not write a return statement - and that value is None. So
    if you assert the tree-not-None as the if condition, you don't even
    need the else part. You could just write:

    def NoneOr (tree, mem_function, *arguments):
    """ if tree is not None then tree.mem_function (arguments).
    """
    if tree is not None:
    return getattr(tree, mem_function)(*arguments)

    Surprisingly, this actually reads almost verbatim from your doc
    string! So I would guess that this implementation is probably closest
    to your original intent for this method. Still, for explicitness'-
    sake, you might want to keep the else-part, just to make your intent
    clear and spelled-out. (Complaining about the presence or absence of
    this bit of code goes beyond "persnickety"...)
    </persnickety>

    Note that the original code is perfectly valid Python, and will run
    just as efficiently as any of my alternative suggestions, which is why
    I enclosed my comments in 'persnickety' (http://
    dictionary.reference.com/browse/persnickety) tags.

    -- Paul
    Paul McGuire, Jul 12, 2008
    #4
  5. Bart Kastermans

    Kay Schluehr Guest

    On 10 Jul., 15:19, Bart Kastermans <> wrote:
    > I am playing with some trees. In one of the procedures I wrote
    > for this I am trying to change self to a different tree. A tree
    > here has four members (val/type/left/right). I found that self = SS
    > does not work; I have to write self.val = SS.val and the same for
    > the other members (as shown below). Is there a better way to do this?
    >
    > In the below self is part of a parse tree, F is the parse tree of a
    > function f with argument x. If a node in the parse tree is labelled
    > f, we should replace it by the parse tree for the function f, F, with
    > the remainder of the tree substituted for the input variable for the
    > function f, here x.
    >
    > def elimF (self):
    > if self.val == "f":
    > SS = F.copy ()
    > SS.subst ('x', self.left)
    > self.val = SS.val # from here: set self to be SS
    > self.type = SS.type
    > self.left = SS.left
    > self.right = SS.right # completed: set self to be SS
    >
    > if self.left != None: # iterate onward, inf recursion if f
    > # appears. Would need a check in
    > # real version
    > self.left.elimF ()
    > if self.right != None:
    > self.right.elimF ()
    >
    > Best,
    > Bart


    Since it is acting on a tree why doesn't the code substitute self in
    its parent by SS? That's the natural perspective if one considers a
    tree as a linked structure and inserts and deletes nodes within this
    structure.
    Kay Schluehr, Jul 12, 2008
    #5
  6. Bart Kastermans

    Terry Reedy Guest

    Kay Schluehr wrote:
    >
    >
    > Since it is acting on a tree why doesn't the code substitute self in
    > its parent by SS? That's the natural perspective if one considers a
    > tree as a linked structure and inserts and deletes nodes within this
    > structure.


    I think you are suggesting the same thing I did:

    > If you examine nodes from their parent, I believe you can do the
    > > substitution in one step. Something like:
    > >
    > > for slot,child in ( ('left',self.left), ('right',self.right) ):
    > > if child is not None:
    > > if child.val == 'f':
    > > setattr(self, slot, F.copy().subst('x', child.left))
    > > child.elimF
    > >
    > > where .subst returns the modified tree.


    Where F.copy is what was called 'SS'. If not, I don't understand.
    Terry Reedy, Jul 12, 2008
    #6
  7. Paul McGuire <> writes:

    > On Jul 12, 6:18 am, Bart Kastermans <kaste...@bart-kastermanss-
    > macbook.local> wrote:
    >> This uses the function:
    >>
    >> def NoneOr (tree, mem_function, *arguments):
    >>     """ if tree is not None then tree.mem_function (arguments). """
    >>     if tree == None:
    >>         return None
    >>     else:
    >>         return getattr (tree, mem_function) (*arguments)
    >>
    >> Bart

    >
    > <persnickety>


    First I want to say these comments are absolutely great. I *very*
    much appreciated getting them. This kind of analysis and thinking
    about code is exactly what I want to learn for myself; so this helped
    me a lot. From the many interesting thoughts I got from this there is
    only one that is a bit dissonant with me; it is the next paragraph.

    > This code reads wrongly to me on a couple of levels. First, I think
    > the general computing consensus is that if-then-else is more readable/
    > logical if you assert the positive condition for the then-part, and
    > put the alternative condition in the else-part. My impression is that
    > the non-None-ness of tree is actually the positive assertion, as in:


    I had been experimenting with exactly this in some of my code. The
    choice seemed to be between (in the cases I had in front of me):

    1) filter out the bad cases and deal with them, then have the code do
    the usual stuff,

    2) set the conditions for being the usual case, then later deal with
    the bad stuff.

    I had been converging towards (1) as in

    def func (inputs):
    if inputs bad one way:
    deal with it

    if inputs bad another way:
    deal with it too

    take care of the generic remaining case

    case (2) would result in something like:

    def func (inputs):
    if inputs are not bad in any way:
    take care of the generic case
    elif in puts bad in one way:
    deal with it
    else: # bad in another way
    deal with it too

    Did I represent the case distinction as you had it in mind? I'll keep
    this more in mind when writing stuff and see how it works out.

    <persnickety>
    Better keep with "more readable", logically these are clearly
    equivalent.
    </persnickety>

    >
    > if tree != None:
    > return getattr(tree, mem_function)(*arguments)
    > else:
    > return None
    >
    > Next, the more Pythonic test for None-ness is most clearly written as:
    >
    > if tree is not None:
    >
    > as there is only one None, and the identity "is not" check is simpler/
    > faster for Python to execute (and possibly - and more importantly -
    > also simpler for readers to follow, as this reads more like a
    > continuous sentence instead of a mixture of prose and mathematical
    > notations).
    >
    > One might even suggest you could further abbreviate this test to:
    >
    > if tree:
    >
    > and get the same behavior. I would quibble with that, however, that
    > this merely exploits a side-effect of Python, in which None values are
    > always False, and *most* non-None values are True. But Python also
    > interprets many non-None values as False, such as 0, or empty
    > containers, such as lists, tuples, dicts, and strings. In fact, your
    > tree class sounds like a structured container to me, and it would be
    > reasonable to assume that you might implement __nonzero__ (pre-Python
    > 2.6) or __bool__ (Python 2.6 and later) in your class to return False
    > for an empty tree, which would still be a valid and not-None tree.
    > You should be able to invoke methods on an empty tree just as one can
    > call "".upper(). So for this case, I would stick with the more
    > explicit "if tree is not None".
    >
    > Another Pythonicity is that methods will *always* return a value, even
    > if you do not write a return statement - and that value is None. So
    > if you assert the tree-not-None as the if condition, you don't even
    > need the else part. You could just write:
    >
    > def NoneOr (tree, mem_function, *arguments):
    > """ if tree is not None then tree.mem_function (arguments).
    > """
    > if tree is not None:
    > return getattr(tree, mem_function)(*arguments)
    >
    > Surprisingly, this actually reads almost verbatim from your doc
    > string! So I would guess that this implementation is probably closest
    > to your original intent for this method. Still, for explicitness'-
    > sake, you might want to keep the else-part, just to make your intent
    > clear and spelled-out. (Complaining about the presence or absence of
    > this bit of code goes beyond "persnickety"...)
    > </persnickety>
    >
    > Note that the original code is perfectly valid Python, and will run
    > just as efficiently as any of my alternative suggestions, which is why
    > I enclosed my comments in 'persnickety' (http://
    > dictionary.reference.com/browse/persnickety) tags.
    >
    > -- Paul
    Bart Kastermans, Jul 13, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stub

    B tree, B+ tree and B* tree

    Stub, Nov 12, 2003, in forum: C Programming
    Replies:
    3
    Views:
    10,091
  2. Ralf W. Grosse-Kunstleve
    Replies:
    16
    Views:
    559
    Lonnie Princehouse
    Jul 11, 2005
  3. Ralf W. Grosse-Kunstleve
    Replies:
    18
    Views:
    579
    Bengt Richter
    Jul 11, 2005
  4. Ralf W. Grosse-Kunstleve
    Replies:
    2
    Views:
    389
    Dan Sommers
    Jul 12, 2005
  5. falcon
    Replies:
    0
    Views:
    358
    falcon
    Jul 31, 2005
Loading...

Share This Page