├── images └── C3_linearization_example.svg.png ├── README.md ├── .gitignore ├── method_overloading.md ├── inheritance.md ├── encapsulation.md ├── code ├── test.py ├── bst.py └── bst1.py └── multiple_inheritance.md /images/C3_linearization_example.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jabhishek87/python-oops/HEAD/images/C3_linearization_example.svg.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-oops 2 | Python Objects Oriented Concepts Explained with Examples 3 | 4 | * [Encapsulation](/encapsulation.md) 5 | * [Method Overloading](/method_overloading.md) 6 | * [inheritance](/inheritance.md) 7 | * [Multiple inheritance (MRO)](/multiple_inheritance.md) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | .idea/ -------------------------------------------------------------------------------- /method_overloading.md: -------------------------------------------------------------------------------- 1 | 2 | > In Python you can define a method in such a way that there are multiple ways to call 3 | > it. This is known as method overloading. We do that by setting default values of 4 | > variables. Let us do an example: 5 | 6 | ```python 7 | class Mobile: 8 | 9 | def get_brand(self, brand=None): 10 | 11 | if brand is not None: 12 | print brand 13 | else: 14 | print 'Generic ' 15 | 16 | # Create instance 17 | obj = Mobile() 18 | 19 | # Call the method 20 | obj.get_brand() 21 | 22 | # Call the method with a parameter 23 | obj.get_brand('Samsung') 24 | 25 | ``` 26 | 27 | #### Output: 28 | 29 | > Hello 30 | 31 | > Hello Samsung 32 | 33 | > To clarify method overloading, we can now call the method sayHello() in two ways: 34 | 35 | ```python 36 | obj.get_brand() 37 | obj.get_brand('Samsung') 38 | ``` 39 | 40 | > We created a method that can be called with fewer arguments than it is defined 41 | > to allow. We are not limited to two variables, your method could have more 42 | > variables which are optional. 43 | 44 | -------------------------------------------------------------------------------- /inheritance.md: -------------------------------------------------------------------------------- 1 | # inheritance 2 | > Classes can inherit functionality from other classes, let’s take a 3 | > look at how that works. We start with a basic class: 4 | 5 | ```python 6 | class User: 7 | name = "" 8 | 9 | def __init__(self, name): 10 | self.name = name 11 | 12 | def printName(self): 13 | print "Name = " + self.name 14 | 15 | brian = User("brian") 16 | brian.printName() 17 | ``` 18 | 19 | > This creates one instance called brian which outputs its given name. 20 | > Add another class called Programmer. 21 | 22 | 23 | ```python 24 | class Programmer(User): 25 | 26 | def __init__(self, name): 27 | self.name = name 28 | def doPython(self): 29 | print "Programming Python" 30 | ``` 31 | 32 | 33 | 34 | > This looks very much like a standard class except than User is given in the 35 | > parameters. This means all functionality of the class User is accesible in the 36 | > Programmer class. 37 | 38 | ### Full example of Python inheritance: 39 | 40 | ```python 41 | class User: 42 | name = "" 43 | 44 | def __init__(self, name): 45 | self.name = name 46 | 47 | def printName(self): 48 | print "Name = " + self.name 49 | 50 | class Programmer(User): 51 | def __init__(self, name): 52 | self.name = name 53 | 54 | def doPython(self): 55 | print "Programming Python" 56 | 57 | brian = User("brian") 58 | brian.printName() 59 | 60 | diana = Programmer("Diana") 61 | diana.printName() 62 | diana.doPython() 63 | ``` 64 | 65 | 66 | > The output: 67 | ```python 68 | Name = brian 69 | Name = Diana 70 | Programming Python 71 | ``` 72 | 73 | > Brian is an instance of User and can only access the method printName. 74 | > Diana is an instance of Programmer, a class with inheritance from User, 75 | > and can access both the methods in Programmer and User. 76 | 77 | -------------------------------------------------------------------------------- /encapsulation.md: -------------------------------------------------------------------------------- 1 | > Encapsulation 2 | > In an object oriented python program, you can restrict access to methods and 3 | > variables. This can prevent the data from being modified by accident and is 4 | > known as encapsulation. Let's start with an example. 5 | 6 | ```python 7 | class Mobile: 8 | 9 | def __init__(self): 10 | self.__update_software() 11 | 12 | def switch_on(self): 13 | print 'driving' 14 | 15 | def __update_software(self): 16 | print 'updating software' 17 | 18 | smobile = Mobile() 19 | smobile.switch_on() 20 | #smobile.__updateSoftware() not accesible from object. 21 | 22 | print('-'*100) 23 | ``` 24 | > Explanation 25 | > The private method __update_software() can only be called within the class 26 | > itself. It can never be called from outside the class. 27 | 28 | 29 | > Private variables 30 | > Variables can be private which can be useful on many occasions. 31 | > Objects can hold crucial data for your application and you do not want that 32 | > data to be changeable from anywhere in the code. An example: 33 | 34 | ```python 35 | class Mobile: 36 | 37 | __os = 'andriod' 38 | __name = "" 39 | 40 | def __init__(self): 41 | self.__os = 'andriod' 42 | self.__name = "Supercar" 43 | 44 | def switch_on(self): 45 | print 'Mobile Os is ' + str(self.__os) 46 | 47 | smobile = Mobile() 48 | smobile.switch_on() 49 | smobile.__os = 'ios' > will not change variable because its private 50 | smobile.switch_on() 51 | print('-'*100) 52 | ``` 53 | > If you want to change the value of a private variable, a setter method is used. 54 | > This is simply a method that sets the value of a private variable. 55 | 56 | ```python 57 | class Mobile: 58 | 59 | __os = 'andriod' 60 | __name = "" 61 | 62 | def __init__(self): 63 | self.__os = 'andriod' 64 | self.__name = "Supercar" 65 | 66 | def switch_on(self): 67 | print 'Mobile Os is ' + str(self.__os) 68 | 69 | def set_os(self, os): 70 | self.__os = os 71 | 72 | smobile = Mobile() 73 | smobile.switch_on() 74 | smobile.set_os('ios') 75 | smobile.switch_on() 76 | 77 | print('-'*100) 78 | ``` 79 | 80 | > Summary 81 | > To summarize, in Python there are: 82 | 83 | Type | Description 84 | --- | --- 85 | public methods | accessible from anywhere 86 | private methods | accessible only in their own class. starts with two underscores 87 | public variables | accessible from anywhere 88 | private variables | accesible only in their own class or by a method if defined. starts with two underscores 89 | -------------------------------------------------------------------------------- /code/test.py: -------------------------------------------------------------------------------- 1 | # lis = [10, 12, 10, 15, -1, 7, 6,5, 4, 2, 1, 1, 1] 2 | 3 | # target = 11 4 | 5 | # res = [] 6 | # for key, value in enumerate(lis): 7 | # cmp_lis = lis[key+1:] 8 | # for j in cmp_lis: 9 | # if value + j == target: 10 | # res.append([value, j]) 11 | 12 | # print(res) 13 | # print(len(res)) 14 | # #print(value, cmp_lis) 15 | 16 | class Tree: 17 | def __init__(self): 18 | self.root = None 19 | 20 | def insert(self, val): 21 | if self.root: 22 | return self.root.insert(val) 23 | else: 24 | self.root = Node(val) 25 | return True 26 | 27 | def preorder(self): 28 | if self.root is not None: 29 | print("Inorder") 30 | self.root.preorder() 31 | 32 | def postorder(self): 33 | if self.root is not None: 34 | print("postorder") 35 | self.root.postorder() 36 | 37 | def inorder(self): 38 | if self.root is not None: 39 | print("inorder") 40 | self.root.inorder() 41 | 42 | 43 | class Node: 44 | def __init__(self, val): 45 | self.value = val 46 | self.left_child = None 47 | self.right_child = None 48 | 49 | 50 | def insert(self, data): 51 | if self.value == data: 52 | return False 53 | 54 | elif self.value > data: 55 | if self.left_child: 56 | self.left_child.insert(data) 57 | return True 58 | else: 59 | self.left_child = Node(data) 60 | return True 61 | else: 62 | if self.right_child: 63 | self.right_child.insert(data) 64 | return True 65 | else: 66 | self.right_child = Node(data) 67 | return True 68 | 69 | def preorder(self): 70 | if self: 71 | print(str(self.value)) 72 | if self.left_child: 73 | self.left_child.preorder() 74 | 75 | if self.right_child: 76 | self.right_child.preorder() 77 | 78 | def postorder(self): 79 | if self: 80 | if self.left_child: 81 | self.left_child.postorder() 82 | 83 | if self.right_child: 84 | self.right_child.postorder() 85 | 86 | print(str(self.value)) 87 | 88 | def inorder(self): 89 | if self: 90 | if self.left_child: 91 | self.left_child.inorder() 92 | 93 | print(str(self.value)) 94 | 95 | if self.right_child: 96 | self.right_child.inorder() 97 | 98 | 99 | 100 | 101 | # bst = Tree() 102 | # for i in [1,2,3,4,5]: 103 | # bst.insert(i) 104 | 105 | # bst.preorder() 106 | st = "abhishek" 107 | print(st.reverse()) 108 | 109 | 110 | -------------------------------------------------------------------------------- /code/bst.py: -------------------------------------------------------------------------------- 1 | # Binary Search Tree in Python 2 | 3 | class Node: 4 | def __init__(self, val): 5 | self.value = val 6 | self.leftChild = None 7 | self.rightChild = None 8 | 9 | def __str__(self): 10 | return str(self.value) + '-'+str(self.leftChild) +'-'+ str(self.rightChild) 11 | 12 | 13 | def insert(self, data): 14 | if self.value == data: 15 | return False 16 | 17 | elif self.value > data: 18 | if self.leftChild: 19 | return self.leftChild.insert(data) 20 | else: 21 | self.leftChild = Node(data) 22 | return True 23 | 24 | else: 25 | if self.rightChild: 26 | return self.rightChild.insert(data) 27 | else: 28 | self.rightChild = Node(data) 29 | return True 30 | 31 | def preorder(self): 32 | if self: 33 | print (str(self.value)) 34 | if self.leftChild: 35 | self.leftChild.preorder() 36 | if self.rightChild: 37 | self.rightChild.preorder() 38 | 39 | 40 | def postorder(self): 41 | if self: 42 | if self.leftChild: 43 | self.leftChild.postorder() 44 | if self.rightChild: 45 | self.rightChild.postorder() 46 | print (str(self.value)) 47 | 48 | def inorder(self): 49 | if self: 50 | if self.leftChild: 51 | self.leftChild.inorder() 52 | print (str(self.value)) 53 | if self.rightChild: 54 | self.rightChild.inorder() 55 | 56 | def lboundary(self): 57 | if self: 58 | if self.leftChild: 59 | print(self.value) 60 | self.leftChild.lboundary() 61 | else: 62 | # dont print if leaf 63 | if self.leftChild and self.rightChild: 64 | print(self.value) 65 | 66 | def leafs(self): 67 | if self: 68 | if self.leftChild: 69 | self.leftChild.leafs() 70 | if self.leftChild is None and self.rightChild is None : 71 | print(self.value) 72 | if self.rightChild: 73 | self.rightChild.leafs() 74 | 75 | def rboundary(self): 76 | if self: 77 | if self.rightChild: 78 | #print(self.value) 79 | self.rightChild.rboundary() 80 | else: 81 | # dont print if leaf 82 | if self.leftChild and self.rightChild: 83 | print(self.value) 84 | 85 | 86 | class Tree: 87 | def __init__(self): 88 | self.root = None 89 | 90 | def insert(self, data): 91 | if self.root: 92 | return self.root.insert(data) 93 | else: 94 | self.root = Node(data) 95 | return True 96 | 97 | def preorder(self): 98 | if self.root is not None: 99 | print("PreOrder") 100 | self.root.preorder() 101 | 102 | def postorder(self): 103 | if self.root is not None: 104 | print("PostOrder") 105 | self.root.postorder() 106 | 107 | def inorder(self): 108 | if self.root is not None: 109 | print("InOrder") 110 | self.root.inorder() 111 | 112 | def boundary(self): 113 | if self.root is not None: 114 | print("Boundary") 115 | self.root.lboundary() 116 | self.root.leafs() 117 | self.root.rboundary() 118 | # self.root.lefts() 119 | # # print all lefts 120 | # self.root.leafs() 121 | # self.root.rights() 122 | 123 | 124 | 125 | def main(): 126 | bst = Tree() 127 | for i in [20,8,22,4,12,10,14,25, 27]: 128 | bst.insert(i) 129 | #bst.insert(7) 130 | # bst.preorder() 131 | # bst.postorder() 132 | # bst.inorder() 133 | bst.boundary() 134 | 135 | main() -------------------------------------------------------------------------------- /multiple_inheritance.md: -------------------------------------------------------------------------------- 1 | # Multiple Inheritance 2 | > In languages that use multiple inheritance, the order in which base classes are 3 | > searched when looking for a method is often called the Method Resolution Order, 4 | > or MRO. 5 | 6 | 7 | * [Explanation by Guido](http://python-history.blogspot.com/2010/06/method-resolution-order.html) 8 | 9 | > lets take an example 10 | 11 | ```python 12 | 13 | class O(): pass 14 | 15 | class A(O): pass 16 | 17 | class B(O): pass 18 | 19 | class C(O): pass 20 | 21 | class D(O): pass 22 | 23 | class E(O): pass 24 | 25 | class K1(A, B, C): pass 26 | 27 | class K2(D, B, E): pass 28 | 29 | class K3(D, A): pass 30 | 31 | class Z(K1, K2, K3): pass 32 | 33 | ``` 34 | 35 | 36 | Image 37 | ![alt text][C3_linearization_example] 38 | 39 | > the linearization of Z is computed as 40 | 41 | ``` 42 | L(O) := [O] // the linearization of O is trivially the singleton list [O], because O has no parents 43 | 44 | L(A) := [A] + merge(L(O), [O]) // the linearization of A is A plus the merge of its parents' linearizations with the list of parents... 45 | = [A] + merge([O], [O]) 46 | = [A, O] // ...which simply prepends A to its single parent's linearization 47 | 48 | L(B) := [B, O] // linearizations of B, C, D and E are computed similar to that of A 49 | L(C) := [C, O] 50 | L(D) := [D, O] 51 | L(E) := [E, O] 52 | 53 | L(K1) := [K1] + merge(L(A), L(B), L(C), [A, B, C]) // first, find the linearizations of K1's parents, L(A), L(B), and L(C), and merge them with the parent list [A, B, C] 54 | = [K1] + merge([A, O], [B, O], [C, O], [A, B, C]) // class A is a good candidate for the first merge step, because it only appears as the head of the first and last lists 55 | = [K1, A] + merge([O], [B, O], [C, O], [B, C]) // class O is not a good candidate for the next merge step, because it also appears in the tails of list 2 and 3, but... 56 | = [K1, A, B] + merge([O], [O], [C, O], [C]) // ...class B qualified, and so does class C; class O still appears in the tail of list 3 57 | = [K1, A, B, C] + merge([O], [O], [O]) // finally, class O is a valid candidate, which also exhausts all remaining lists 58 | = [K1, A, B, C, O] 59 | 60 | L(K2) := [K2] + merge(L(D), L(B), L(E), [D, B, E]) 61 | = [K2] + merge([D, O], [B, O], [E, O], [D, B, E]) // select D 62 | = [K2, D] + merge([O], [B, O], [E, O], [B, E]) // fail O, select B 63 | = [K2, D, B] + merge([O], [O], [E, O], [E]) // fail O, select E 64 | = [K2, D, B, E] + merge([O], [O], [O]) // select O 65 | = [K2, D, B, E, O] 66 | 67 | L(K3) := [K3] + merge(L(D), L(A), [D, A]) 68 | = [K3] + merge([D, O], [A, O], [D, A]) // select D 69 | = [K3, D] + merge([O], [A, O], [A]) // fail O, select A 70 | = [K3, D, A] + merge([O], [O]) // select O 71 | = [K3, D, A, O] 72 | 73 | L(Z) := [Z] + merge(L(K1), L(K2), L(K3), [K1, K2, K3]) 74 | = [Z] + merge([K1, A, B, C, O], [K2, D, B, E, O], [K3, D, A, O], [K1, K2, K3]) // select K1 75 | = [Z, K1] + merge([A, B, C, O], [K2, D, B, E, O], [K3, D, A, O], [K2, K3]) // fail A, select K2 76 | = [Z, K1, K2] + merge([A, B, C, O], [D, B, E, O], [K3, D, A, O], [K3]) // fail A, fail D, select K3 77 | = [Z, K1, K2, K3] + merge([A, B, C, O], [D, B, E, O], [D, A, O]) // fail A, select D 78 | = [Z, K1, K2, K3, D] + merge([A, B, C, O], [B, E, O], [A, O]) // select A 79 | = [Z, K1, K2, K3, D, A] + merge([B, C, O], [B, E, O], [O]) // select B 80 | = [Z, K1, K2, K3, D, A, B] + merge([C, O], [E, O], [O]) // select C 81 | = [Z, K1, K2, K3, D, A, B, C] + merge([O], [E, O], [O]) // fail O, select E 82 | = [Z, K1, K2, K3, D, A, B, C, E] + merge([O], [O], [O]) // select O 83 | = [Z, K1, K2, K3, D, A, B, C, E, O] // done 84 | ``` 85 | 86 | ## Example demonstrated in Python 87 | 88 | ```python 89 | class A(object): pass 90 | 91 | class B(object): pass 92 | 93 | class C(object): pass 94 | 95 | class D(object): pass 96 | 97 | class E(object): pass 98 | 99 | class K1(A, B, C): pass 100 | 101 | class K2(D, B, E): pass 102 | 103 | class K3(D, A): pass 104 | 105 | class Z(K1, K2, K3): pass 106 | 107 | Z.mro() 108 | ``` 109 | > output 110 | ```python 111 | [, , , , , , , , , ] 112 | 113 | [Z, K1, K2, K3, D, A, B, C, E, ] 114 | 115 | 116 | ``` 117 | [References][wiki_link] 118 | 119 | 120 | [C3_linearization_example]: images/C3_linearization_example.svg.png "Logo Title Text 2" 121 | [wiki_link]: https://en.wikipedia.org/wiki/C3_linearization#example -------------------------------------------------------------------------------- /code/bst1.py: -------------------------------------------------------------------------------- 1 | # Binary Search Tree in Python 2 | 3 | class Node: 4 | def __init__(self, val): 5 | self.value = val 6 | self.leftChild = None 7 | self.rightChild = None 8 | 9 | def insert(self, data): 10 | if self.value == data: 11 | return False 12 | 13 | elif self.value > data: 14 | if self.leftChild: 15 | return self.leftChild.insert(data) 16 | else: 17 | self.leftChild = Node(data) 18 | return True 19 | 20 | else: 21 | if self.rightChild: 22 | return self.rightChild.insert(data) 23 | else: 24 | self.rightChild = Node(data) 25 | return True 26 | 27 | # def find(self, data): 28 | # if(self.value == data): 29 | # return True 30 | # elif self.value > data: 31 | # if self.leftChild: 32 | # return self.leftChild.find(data) 33 | # else: 34 | # return False 35 | # else: 36 | # if self.rightChild: 37 | # return self.rightChild.find(data) 38 | # else: 39 | # return False 40 | 41 | # def getSize(self): 42 | # if self.leftChild and self.rightChild: 43 | # return 1 + self.leftChild.getSize() + self.rightChild.getSize() 44 | # elif self.leftChild: 45 | # return 1 + self.leftChild.getSize() 46 | # elif self.rightChild: 47 | # return 1 + self.rightChild.getSize() 48 | # else: 49 | # return 1 50 | 51 | # def getHeight(self): 52 | # if self.leftChild and self.rightChild: 53 | # return 1 + max(self.leftChild.getHeight(), self.rightChild.getHeight()) 54 | # elif self.leftChild: 55 | # return 1 + self.leftChild.getHeight() 56 | # elif self.rightChild: 57 | # return 1 + self.rightChild.getHeight() 58 | # else: 59 | # return 1 60 | 61 | def preorder(self): 62 | if self: 63 | print (str(self.value)) 64 | if self.leftChild: 65 | self.leftChild.preorder() 66 | if self.rightChild: 67 | self.rightChild.preorder() 68 | 69 | def postorder(self): 70 | if self: 71 | if self.leftChild: 72 | self.leftChild.postorder() 73 | if self.rightChild: 74 | self.rightChild.postorder() 75 | print (str(self.value)) 76 | 77 | def inorder(self): 78 | if self: 79 | if self.leftChild: 80 | self.leftChild.inorder() 81 | print (str(self.value)) 82 | if self.rightChild: 83 | self.rightChild.inorder() 84 | 85 | class Tree: 86 | def __init__(self): 87 | self.root = None 88 | 89 | def insert(self, data): 90 | if self.root: 91 | return self.root.insert(data) 92 | else: 93 | self.root = Node(data) 94 | return True 95 | 96 | # def find(self, data): 97 | # if self.root: 98 | # return self.root.find(data) 99 | # else: 100 | # return False 101 | 102 | # def getHeight(self): 103 | # if self.root: 104 | # return self.root.getHeight() 105 | # else: 106 | # return 0 107 | 108 | # def getSize(self): 109 | # if self.root: 110 | # return self.root.getSize() 111 | # else: 112 | # return 0 113 | 114 | # def remove(self, data): 115 | # # empty tree 116 | # if self.root is None: 117 | # return False 118 | 119 | # # data is in root node 120 | # elif self.root.value == data: 121 | # if self.root.leftChild is None and self.root.rightChild is None: 122 | # self.root = None 123 | # elif self.root.leftChild and self.root.rightChild is None: 124 | # self.root = self.root.leftChild 125 | # elif self.root.leftChild is None and self.root.rightChild: 126 | # self.root = self.root.rightChild 127 | # elif self.root.leftChild and self.root.rightChild: 128 | # delNodeParent = self.root 129 | # delNode = self.root.rightChild 130 | # while delNode.leftChild: 131 | # delNodeParent = delNode 132 | # delNode = delNode.leftChild 133 | 134 | # self.root.value = delNode.value 135 | # if delNode.rightChild: 136 | # if delNodeParent.value > delNode.value: 137 | # delNodeParent.leftChild = delNode.rightChild 138 | # elif delNodeParent.value < delNode.value: 139 | # delNodeParent.rightChild = delNode.rightChild 140 | # else: 141 | # if delNode.value < delNodeParent.value: 142 | # delNodeParent.leftChild = None 143 | # else: 144 | # delNodeParent.rightChild = None 145 | 146 | # return True 147 | 148 | # parent = None 149 | # node = self.root 150 | 151 | # # find node to remove 152 | # while node and node.value != data: 153 | # parent = node 154 | # if data < node.value: 155 | # node = node.leftChild 156 | # elif data > node.value: 157 | # node = node.rightChild 158 | 159 | # # case 1: data not found 160 | # if node is None or node.value != data: 161 | # return False 162 | 163 | # # case 2: remove-node has no children 164 | # elif node.leftChild is None and node.rightChild is None: 165 | # if data < parent.value: 166 | # parent.leftChild = None 167 | # else: 168 | # parent.rightChild = None 169 | # return True 170 | 171 | # # case 3: remove-node has left child only 172 | # elif node.leftChild and node.rightChild is None: 173 | # if data < parent.value: 174 | # parent.leftChild = node.leftChild 175 | # else: 176 | # parent.rightChild = node.leftChild 177 | # return True 178 | 179 | # # case 4: remove-node has right child only 180 | # elif node.leftChild is None and node.rightChild: 181 | # if data < parent.value: 182 | # parent.leftChild = node.rightChild 183 | # else: 184 | # parent.rightChild = node.rightChild 185 | # return True 186 | 187 | # # case 5: remove-node has left and right children 188 | # else: 189 | # delNodeParent = node 190 | # delNode = node.rightChild 191 | # while delNode.leftChild: 192 | # delNodeParent = delNode 193 | # delNode = delNode.leftChild 194 | 195 | # node.value = delNode.value 196 | # if delNode.rightChild: 197 | # if delNodeParent.value > delNode.value: 198 | # delNodeParent.leftChild = delNode.rightChild 199 | # elif delNodeParent.value < delNode.value: 200 | # delNodeParent.rightChild = delNode.rightChild 201 | # else: 202 | # if delNode.value < delNodeParent.value: 203 | # delNodeParent.leftChild = None 204 | # else: 205 | # delNodeParent.rightChild = None 206 | 207 | def preorder(self): 208 | if self.root is not None: 209 | print("PreOrder") 210 | self.root.preorder() 211 | 212 | def postorder(self): 213 | if self.root is not None: 214 | print("PostOrder") 215 | self.root.postorder() 216 | 217 | def inorder(self): 218 | if self.root is not None: 219 | print("InOrder") 220 | self.root.inorder() 221 | 222 | def main(): 223 | bst = Tree() 224 | print(bst.insert(10)) 225 | print(bst.insert(5)) 226 | bst.insert(2) 227 | bst.insert(7) 228 | # bst.preorder() 229 | # bst.postorder() 230 | bst.inorder() 231 | 232 | main() --------------------------------------------------------------------------------