How could I recursively iterate through nodes with reference to a previous node? Expecting output 4,3,2,1 in the example below:
class Node:
def __init__(self, parent, value):
self.parent = parent
self.value = value
def append(self, value):
return Node(self, value)
def list(l):
print(l.value)
while l.parent is not None:
list(l.parent)
l = Node(None, 1)
l = l.append(2)
l = l.append(3)
l = l.append(4)
list(l)
Your class structure already succesfully passes the node's self value to its child node. The problem is your list function. while l.parent is not None: never ends, because nothing in the loop is changing the value of l. Calling list recursively will create a new context where another variable named l has a different value from the first context's l, but this has no effect on the the first l or the first loop. Recursive functions generally do not require an actual loop in order to iterate over the elements of a data structure. Try:
def list(l):
print(l.value)
if l.parent is not None:
list(l.parent)
Or:
def list(l):
while l is not None:
print(l.value)
l = l.parent
(I recommend the latter because the first one will crash with "maximum recursion depth exceeded" if the chain has more than 999 elements)
Result:
4
3
2
1
Bonus style tip: consider naming your function something other than list. In general you should avoid overwriting the names of built-in functions and types.
I should vote to close your question for the lack of a clear problem statement, but anyway...
Within an object in Python, how can I pass a reference of my current object
The same way as you'd do with just any object.
to object b of the same class
This is actually irrelevant but anyway...
such that when I call b.parent, I can get back to object a?
class Foo(object):
def __init__(self, parent=None):
self.parent = parent
a = Foo()
b = Foo(a)
print(b.parent is a)
Now for the answer to the question you didn't ask, see (and accept) Kevin's answer ;-)
Related
I'm studying for a python course and one of the exercise was to create a decorator for this class that returns every int variables.`
#decoratoreDiClasse
class MyClass:
def __init__(self):
self.a = 1
self.b = 2
self.c = 'w'`
My problem is that the list is always empty beacuse dict does not return the variables inside init,how can i solve my problem?
i've written my decorator below
def decoratoreDiClasse(cls):
def elencaVariabili():
lista = []
print(cls)
lista1 = cls.__dict__
print(lista1)
for ab in lista1:
if isinstance(ab, int):
lista.append(ab)
return lista
setattr(cls, "elencaVariabili", elencaVariabili())
return cls
here's the part of the main that should print the variables,I cannot change anything apart from "decoratoreDiClasse" due to the teacher request.
for v in x.elencaVariabili():
print(v, end=' ')
It looks like you're supposed to have your decorator add a method to the class that prints out integer-valued attributes on an instance it's called on. That's not what you're currently trying to do, as your code tries to find the variables on the class instead of on an instance later on.
Think of what you're doing as a method, and it will be a lot simpler:
def decoratoreDiClasse(cls):
def elencaVariabili(self): # this is a method, so it should take self!
lista = [value for value in self.__dict__.values() # loop over our attribute values
if isinstance(value, int)] # and pick out the integers!
return lista
setattr(cls, "elencaVariabili", elencaVariabili) # don't call the method here
return cls
It's not entirely clear from your code if you're supposed to be returning the names of the integer variables or just the values themselves. I went with just the values, but if you need the variable names, you may need to change the list comprehension to iterate over the items() of the instance's dictionary rather than just the values().
A tree (such as an inheritance tree) is a data structure
with parent nodes and child nodes. For example
A
/ |
B C
/ | |
D E F
We will represent the tree a a dictionary with node name as key, and
list of child names values.
{"A":["B", "C"], "B":["D","E"], "C":["F"], "D":[], "E":[], "F":[]}
Consider each ordered list and use recursion to traverse the list
'depth first`.
Return a string of letters in order of visiting during depth first traversal.
For this example, the system should return "ABDECF"
:param parent: current node being processed
:param tree: dictionary of the entire tree - do not modify this in recursive call
:return: String representing depth first traversal
I understand inheritance pretty well, I just don't understand what exactly I am supposed to do with it in this case. Any help would be appreciated.
class Program4:
def __init__(self):
self.counter=0
def traverse(self, parent, tree):
self.counter += 1 # Leave this counter alone
##todo - fix this.
# call recursion with self since instance method
# This is doable in no more than six lines of code
pass
if __name__ == "__main__":
tree = {"A":["B", "C"], "B":["D","E"], "C":["F"], "D":[], "E":[], "F":[]}
print("Tree:",tree)
p=Program4()
print("Depth first:",p.traverse("A",tree))
Something like the following will do:
class Program4:
# ...
def traverse(self, parent, tree):
# ...
s = parent
for child in tree.get(parent, []):
s += self.traverse(child, tree)
return s
The base case case is a leaf node without children in which case (as you can verify) the parent itself is returned. In all other cases the traversals of the parent's subtrees are appended to it.
You could do that in a one-liner, using str.join and a generator:
# ...
def traverse(self, parent, tree):
return parent + ''.join(self.traverse(c, tree) for c in tree.get(parent, []))
>>> p = Program4()
>>> print("Depth first:", p.traverse("A", tree))
Depth first: ABDECF
I am currently working on LinkedList and I have the following code and I don't understand what the __iter__ and __repr__ are doing exactly?
class Node:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, value):
if self.head is None:
self.head = Node(value)
return
node = self.head
while node.next:
node = node.next
node.next = Node(value)
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def __repr__(self):
return str([v for v in self])
Here I am creating the LinkedList and append the values at the end of my list.
llist = LinkedList()
for value in [4,2,5,1,-3,0]:
llist.append(value)
If I print the list print(llist) then I am getting [4, 2, 5, 1, -3, 0]
I guess this is coming from __iter__ and __repr__. What I don't understand is when my __iter__ and __repr__ starts and which is running first? How can I print objects outside my class?
From my limited understanding of Python internals, when you print() an object, the str() function is called on it. This function probably knows how to format some kinds of objects, such as strings and numbers, for others, it calls their __repr__() method which is supposed to return a string. So __repr__() is called first.
The __repr__() method was written by the developer to return a normal list representation which is created by the list comprehension [v for v in self]. The iteration ultimately calls the __iter__() method which is a generator function (as indicated by the use of yield). This function iterates over the elements of the list, and every yield makes one element available to the for ... in ... construct.
Read the docs.
iter: defines on what attribute/how iterating on a class' object is supposed to work - e.g. what is "next". If you wanted say to iterate on animals, and you wanted the iteration to be defined by each animal's weight, then you could use self.weight in your animal class much in the way that you're using self.value right now....
_ repr _: When you do print(my_Object), Python by default has a representation (repr) defined. You can re-define using this function.
when you are implementing the iter method, you are changing the behaviour of looping throught your list.
what I mean is in the normal for loop when you call:
for l in list:
print(l)
this what will happen behind the scene :
# create an iterator object from that iterable
iter_obj = iter(list)
# infinite loop
while True:
try:
# get the next item
element = next(iter_obj)
# do something with element
except StopIteration:
# if StopIteration is raised, break from loop
break
so if you redefine the iter function inside your linked list class you are redefining the iteration function and what should iterating through your iterator returns.
same basically for repr you redefine the represantation of your object. for example when you call print(obj) you get the obj printed but you can change it to the format you want to if you implement repr correctly as you wish.
take a look here for more explaination:
https://www.programiz.com/python-programming/iterator
https://www.pythonforbeginners.com/basics/str-vs-__repr
__iter__ represents the iterator method of the class. Let's understand through code:
llist = LinkedList()
for value in [4,2,5,1,-3,0]:
llist.append(value)
for value in llist:
print(value)
Output
4
2
5
1
-3
0
Here, when we take the object as an iterator, __iter__() method would be into action which iterates and traverse linked list and yields node values.
print(llist)
Output
[4, 2, 5, 1, -3, 0]
Here, __repr__() method would be into action and would print node values as specified in the code.
I have the following class:
class Node():
def __init__(self, symbol, rule, children):
self.symbol = symbol
self.rule = rule
self.children = children
def addChild(self,child):
self.children.append(child)
I use it to build parsing trees; now I'm trying to use this function:
def simplify(n):
if len(n.children) == 0:
return n
if len(n.children) > 1:
for c in n.children:
c = simplify(c)
return n
while len(n.children) == 1:
print n.symbol,
n = n.children[0] #What is wrong here?
print n.symbol
return n
to simplify trees by removing internal nodes that have just one child. For instance:
S S
/ \ should become / \
E X v X
/
v
When I run the code, the two print statements show me that n was correctly replaced by n.children[0] , but when the tree is printed (right after this funtion is used), I see the same one. What's the problem here?
In your simplify() function, the parameter n is a reference to some specific node, and you can change what node it refers to; but reassigning n doesn't change any of the other structure. As a specific example, this loop actually does nothing:
for c in n.children:
# simplify has no side effects and leaves the input structure unchanged
c = simplify(c)
# c is never used again so the simplified result is lost
There's two reasonable approaches to solving this. One is to construct a new tree as the result of simplify:
def simplify(n):
if len(n.children) > 1:
new_children = [simplify(c) for c in n.children]
return Node(n.symbol, n.rule, new_children)
# and other cases
This has the advantage that your data structure is immutable: if you have two references to the tree hanging around, you know that rewriting one isn't going to destroy the other; if you have a reference to a node in the middle of the tree, there's no risk of it unexpectedly becoming "orphaned".
Still, it is common enough to see mutable data structures, and you could add your simplify method into the Node class to rewrite a node in place:
class Node:
def simplify(self):
if len(self.children) == 1:
return self.children[0].simplify()
if len(self.children) > 1:
self.children = [c.simplify() for c in self.children]
return self
[Sorry, I'm new in Python. Although it seems to be a very basic question, I did my share of due diligence before asking this audience, trying to avoid really stupid questions].
I'm trying to figure out the correct idiom for returning an l-value from a function. Assume I've a container of 64 objects, and I want to be able to return a reference to these objects.
class ChessBoard:
def __init__(self):
self.squares = [None for x in range(64)]
square( row, col ):
return self.squares(row*8+col) <---- I'd like this to be l-value
Then, from outside the class I want to:
board = ChessBoard()
board.square(0,0) = Piece( Shapes.ROOK, Colors.White ) <-- I'm getting an error here
board.square(0,1) = Piece( Shapes.BISHOP, Colors.White )
... etc.
So, I would like the function 'at' to return a lvalue (Something like a reference in C++), but I can't find anything resembling a reference or a pointer in the language. If I stored a list in each square containing one Piece, it is possible I could do something like: board.square(0,0)[0] = Piece - but it seems crazy (or maybe not - as I said, I'm new to the language).
How would you approach this data structure?
In Python, everything is a reference. The only problem is that None is immutable, so you can't use the returned reference to change the value.
You also can't override the assignment operator, so you won't get this particular kind of behaviour. However, a good and very flexible solution would be to override the __setitem__ and __getitem__ methods to implement the subscription operator ([]) for the class:
class ChessBoard(object):
def __init__(self):
self.squares = [None] * 64
def __setitem__(self, key, value):
row, col = key
self.squares[row*8 + col] = value
def __getitem__(self, key):
row, col = key
return self.squares[row*8 + col]
Usage:
>>> c = ChessBoard()
>>> c[1,2] = 5
>>> c[1,2]
5
You can try something like this, at the cost of having to put bogus [:] indexers around:
class Board:
def __init__(self):
self.squares=[None for x in range(64)]
def square(self, row, col):
squares=self.squares
class Prox:
def __getitem__(self, i):
return squares[row*8+col]
def __setitem__(self, i, v):
squares[row*8+col]=v
return Prox()
Then you can do
b=Board()
b.square(2,3)[:]=Piece('Knight')
if b.square(x,y)[:] == Piece('King') ...
And so on. It doesn't actually matter what you put in the []s, it just has to be something.
(Got the idea from the Proxies Perl6 uses to do this)
As Niklas points out, you can't return an l-value.
However, in addition to overriding subscription, you can also use properties (an application of descriptors: http://docs.python.org/howto/descriptor.html) to create an object attribute, which when read from, or assigned to, runs code.
(Not answering your question in the title, but your "How would you approach this data structure?" question:) A more pythonic solution for your data structure would be using a list of lists:
# define a function that generates an empty chess board
make_chess_board = lambda : [[None for x in xrange(8)] for y in xrange(8)]
# grab an instance
b = make_chess_board()
# play the game!
b[0][0] = Piece(Shapes.ROOK, Colors.White)
b[0][1] = Piece(Shapes.BISHOP, Colors.White)
# Or use tuples:
b[0][0] = (Shapes.ROOK, Colors.White)
b[0][1] = (Shapes.BISHOP, Colors.White)