To practice python, I made a simple class for a tree structure in which each node can have infinite child nodes.
class Tree():
def __init__(self, children, val):
self.children = children
self.val = val
def add(self, child):
self.children.append(child)
def remove(self, index):
child = self.children[index]
self.children.remove(child)
return child
def print(self):
self.__print__(0)
def __print__(self, indentation):
valstr = ''
for i in range(0, indentation):
valstr += ' '
valstr += self.val
for child in self.children:
child.__print__(indentation + 1)
However, I have a syntax error in the line def print(self):. Where is the error? I have been looking for a long time, and it seems like the right way to define a python function.
I have also tried
#override
def print(self):
self.__print__(0)
to no avail.
In Python 2 print is a keyword, so you can't use it as the name of a function or method.
In Python 2.7 (and maybe other versions) you can override the print statement with a print function and than override that function.
To do that you have to add
from __future__ import print_function
as the first line of your file.
In Python 2 print is a reserved word and cannot be the name of a variable or method or function.
Related
I have to do an unrolled linked list for one of my classes. I'm new to python, but not to programming, and for some reason I cannot get around this little problem!
I have a class Node that is to be the node object used within the unrolled linked list. The unrolled linked list class performs all the operations on the Node class.
class UnrolledLinkedList(object):
""" INNER NODE CLASS """
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
""" END NODE CLASS """
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = Node()
""" OTHER FUNCTIONS OF UNROLLEDLINKEDLIST CLASS """
The problem comes at the last line of the UnrolledLinkedList class' init function: "global name Node is not defined". I double checked my indentation and looked all over the internet for examples of something like this, but couldn't find any. Would someone mind explaining to me what's wrong?
Methods do not include their class as a scope to be searched. If you want this to work then you will need to use either UnrolledLinkedList.Node or self.Node instead.
The inner class Node is a member of the class UnrolledLinkedList and can only be accessed via self.
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = self.Node()
Use:
self.head = self.Node()
and it works.
A class does not create its own name space. Using self.Node(), Python first searches all attributes of the instances. Since it does not find the name Node there, it it searches the class UnrolledLinkedList for Node.
Alternatively, you can use the class name directly:
UnrolledLinkedList.Node()
You can achieve the same without nesting the class Node:
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
class UnrolledLinkedList(object):
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = Node()
Qualify Node() with self:
class UnrolledLinkedList(object):
class Node(object):
def __init__(self):
self.array = []
self.next_node = None
def __init__(self, max_node_capacity=16):
self.max_node_capacity = max_node_capacity
self.head = self.Node()
Python needs to qualify references to things. In this case, you could either say UnrolledLinkedList.Node() or self.Node().
I wanna create a class which consist of parents and children and a recursion method to call the last child :
class MyClass:
def __init__(self,val,child =None):
self.val = val
self.child = child
def findLastChildVal(self):
if self.child ==None:
return self.val
return (...)
c = MyClass("I'm child")
p = MyClass("I'm parent",c)
p.findLastChildVal()
I have no Idea what to write instead of (...). It's confusing.
This is a classic recursion problem, in my opinion it will be much easier to use a static function instead of a member function:
class MyClass:
def __init__(self, val, child =None):
self.val = val
self.child = child
#staticmethod
def find_last_child_val(current_node: MyClass):
if current_node.child == None:
return current_node.val
else:
return MyClass.find_last_child_val(current_node.child)
c = MyClass("I'm child")
p = MyClass("I'm parent", c)
MyClass.find_last_child_val(p)
Update:
Pay attention that searching for a child using a recursion like this, is not efficient. find_last_child_val() runs in O(n) complexity. It is much more efficient to perform n iterations in a for loop instead of a recursion. If you can't think of a way to reduce the tree traversal complexity, I suggest using a different data structure.
Let's say I have a simple linked list class:
class LL:
def __init__(self):
self.next = None
self.previous = None
def next(self):
return self.next
def previous(self):
return self.previous
In this case, I want to invoke previous or next, based on what is passed into a function in another class, like so:
class foo:
def __init__(self):
self.node = LL()
def move(direction):
self.node = self.node.direction
S.t. when it makes a call, it would call self.node.next() or self.node.previous().
Where move("next") would make a call to self.node.next().
This doesn't work. Nor does
self.node = self.node.direction()
How would I go about accomplishing something like this?
I'm not sure how to even formally describe this- assigning a class attribute by calling an alternate class' method via a parameter?
For your case, it would be best to keep it simple with an if statement.
def move(direction):
if direction == 'next':
self.node = self.node.next()
elif direction == 'previous':
self.node = self.node.previous()
else:
#handle the invalid input however you think is best
However, you should rename either the field or the method for both next and previous. I would recommend changing next(self) to getNext(self). Alternately, you could change self.next to self._next to indicate that the field is not intended to be accessed directly.
As #user2357112 demonstrated, your LL class itself has shadowing issues. You'll probably want to modify it to perhaps one of the following:
class LL:
def __init__(self):
self._next = None
self._previous = None
# assign a different name
def next(self):
... do something like move the node to next
... maybe change self._next on the way...
return self._next
# Or make use of property decorator
#property
def previous(self):
... do something like move the node to previous
return self._previous
#previous.setter
def previous(self, value):
... do something to change self._previous
Somehow I still don't think that's what you're after, but to answer the spirit of your question, you can use a dict like a switch statement in your foo() class like so:
class foo:
def __init__(self):
self.node = LL()
def move(direction):
_moves = {
'next': self.node.next,
'previous': self.node.previous,
'nowhere': self.node.nowhere
}
# if you're invoking a method
_moves.get(direction)()
# if you're just referencing an attribute
_moves.get(direction)
Conceptually I think it's more important to think about what you're trying to achieve with LL and foo before proceeding though.
I've got a binary search tree full of objects. I'm traversing the tree using a callback function that adds a property of all the objects to a global variable. I've got this working, but I'd like to find a way to accomplish this without using a global.
Here's the relevant code:
TOTAL_AGE = 0.0
class Node(object):
def __init__(self, data):
self.left = None
self.right = None
self.data = data
class Tree(object):
def __init__(self):
self.root = None
self.size = 0
def traverse(self, callback):
self._traverse(callback, self.root)
def _traverse(self, callback, node):
if node is None:
return
self._traverse(callback, node.left)
callback(node.data)
self._traverse(callback, node.right)
def add_ages(tree):
tree.traverse(callback)
def callback(student):
global TOTAL_AGE
TOTAL_AGE += student.age
def main():
tree = bst.Tree()
add_ages(tree)
print TOTAL_AGE
This is admittedly for an assignment, which requires that I use the current traverse function and not a different implementation. That's mainly my issue though because I don't see a way to do this without using a global or modifying traverse().
Thanks in advance for any help.
You could pass a method of a class instance as callback so that you can keep track of the state in the instance:
class Count(object):
def __init__(self):
self.total_age = 0
def callback(self, student):
self.total_age += student.age
And then instantiate Count and pass its callback method to the Tree:
count = Count()
tree.traverse(count.callback)
Learning Python and I ran into some problems when I was working on making a linked list class.
This is just a quick node and dirty node class. In java I would of down private Node next and private int val but I only knew of global as the python cousin. How does this look?
#class Node class
class Node(object):
global next
global val
def __init__(self):
next
val
def setNext(self, aNext):
self.next = aNext
def getNext(self):
return self.next
def setVal(self, aVal):
self.val = aVal
def getVal(self):
return self.val
Then I tried to use a Node in another class with
from Node import *
head = Node()
How ever I am getting an error of undefined variable. Sorry for the simple question just new to python. Appreciate the help.
I would implement this this way:
class Node(object):
def __init__(self, next=None, val=None):
self.next = next
self.val = val
That's it. No getters or setters - Python doesn't use them. Instead, you refactor into a property if you need to move away from the basic attribute reference logic.
You can then create nodes with or without values or successors:
tailnode = Node()
tailnode.val = 'foo'
midnode = Node(val='bar')
midnode.next = tailnode
headnode = Node(val='baz', next=midnode)
You don't need the "global val" / "global next" .. It's a mistake even.
instead just write
val = None
next = None
and initiate them in the __init__()
Meaning, the first lines in your class should be like:
class Node(object):
# You can choose whether to initialize the variables in the c'tor or using your setter methods
def __init__(self, val=None, next=None):
self.next = next
self.val = val
If you really want private variables in Python… then you don't want private variables, and should read Peter DeGlopper's answer.
If you still really, really want private variables in Python… well, you can't have them. But you can have "cooperatively private" variables—variables that nobody will find unless they go looking for them, and that won't clutter the screen when you introspect things in the interpreter, and so on, and, most importantly, that Python programmers know, by convention, that they aren't supposed to touch. All you have to do is start the name with an underscore.
However, your code isn't creating member variables at all, for a number of reasons.
First, global does not declare or define a variable; all it does is tell Python, "when you see this variable later, don't use the normal rules to figure out if it's local or global, always use the global copy". You still have to assign a value to the variable somewhere; otherwise, you'll get a NameError.
Next, variables that you assign in the class definition are class members—similar to Java's static members, although not identical. Each class member is shared by all instances of the class. That's not what you want here; each Node is supposed to have its own separate val and next, not share one with all other Nodes, right?
Normal instance member variables are always accessed through dot syntax—as self.foo from inside the class's methods, or as spam.foo from outside.
So, where do you declare those? You don't. Python doesn't declare anything. You can add new members to an object at any time. The usual way to create a standard set of instance members is in the __init__ method:
class Node(object):
def __init__(self):
self._next = None
self._val = None
def setNext(self, aNext):
self._next = aNext
def getNext(self):
return self._next
def setVal(self, aVal):
self._val = aVal
def getVal(self):
return self._val
But really, you can just let the setters create them. That way, you'll catch the error if someone calls getNext without having called setNext first (which is, I assume, illegal).
class Node(object):
def setNext(self, aNext):
self._next = aNext
def getNext(self):
return self._next
def setVal(self, aVal):
self._val = aVal
def getVal(self):
return self._val
Or, alternatively, force the user to initialize the object with valid values at construction time:
def __init__(self, next, val):
self._next = next
self._val = val
Again, there's no good reason to use setters and getters in the first place in Python.
So, the simplest implementation of your class is:
class Node(object):
pass
While the most Pythonic is:
class Node(object):
def __init__(self, next, val):
self.next = next
self.val = val
… which, you'll notice, is Peter DeGlopper's answer, which, as I said at the start, is probably what you want. :)
Python doesn't really use private variables.
Something like this would be best:
class Node(object):
def __init__(self):
self.val = None
self.next = None
Then, you make and set the node like this:
>>> node = Node()
>>> node.val = 5
>>> node2 = Node()
>>> node2 = 1
>>> node.next = node2
>>> node.next.val
1
If you want to create node with Node(5, Node(1)), use:
class Node(object):
def __init__(self, value=None, next=None):
self.value = value
self.next = next