1 = Program Structure = 2 3 A program consists of a number of '''modules''' with each module providing its 4 own namespace. Modules can be organised within '''packages''' which define a 5 hierarchical relationship between them. However, the relationship between 6 modules is not automatically exposed within the program: it is more 7 appropriate to consider modules as independent entities that have a particular 8 naming scheme. 9 10 Within each module a hierarchy of namespaces is provided by '''classes''', 11 with each class potentially containing other classes, and so on. Also 12 appearing within modules and classes are '''functions''', with those appearing 13 within classes being regarded as '''methods'''. 14 15 Function namespaces are considered separately from module and class namespaces 16 and are not considered part of the general namespace hierarchy, instead merely 17 appearing as objects at the edges of that hierarchy. Functions may also be 18 defined within functions, and such inner functions will be referenced within 19 their parent functions, but no hierarchical relationship will exist between 20 their namespaces. 21 22 Thus, a program provides a static namespace hierarchy consisting of modules 23 containing classes (containing other classes, and so on) plus functions. 24 Objects residing within namespaces are accessed via '''attributes''' of those 25 namespaces. 26 27 {{{{#!table 28 {{{#!graphviz 29 //format=svg 30 //transform=notugly 31 digraph program { 32 node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Program structure"]; 33 edge [tooltip="Program structure"]; 34 rankdir=LR; 35 36 program [label="program",shape=folder,style=filled,fillcolor=cyan]; 37 38 subgraph { 39 rank=same; 40 moduleM [label="module M",style=filled,fillcolor=gold]; 41 moduleN [label="module N\n(package)",style=filled,fillcolor=gold]; 42 } 43 44 subgraph { 45 rank=same; 46 classA [label="class A"]; 47 moduleNP [label="module N.P",style=filled,fillcolor=gold]; 48 } 49 50 subgraph { 51 rank=same; 52 functionF [label="function f",shape=ellipse]; 53 functionG [label="function g",shape=ellipse]; 54 classB [label="class B"]; 55 classC [label="class C"]; 56 } 57 58 subgraph { 59 rank=same; 60 functionJ [label="function j",shape=ellipse]; 61 functionH [label="function h",shape=ellipse]; 62 functionK [label="function k",shape=ellipse]; 63 } 64 65 program -> moduleM; 66 program -> moduleN; 67 68 moduleM -> classA; 69 moduleN -> moduleNP; 70 moduleNP -> classC; 71 72 classA -> functionF; 73 classA -> functionG; 74 classA -> classB; 75 classB -> functionH; 76 classC -> functionK; 77 78 functionG -> functionJ [style=dashed]; 79 } 80 }}} 81 || 82 {{{#!python numbers=disable 83 # module M 84 85 class A: 86 def f(...): pass 87 88 def g(...): 89 def j(...): pass 90 91 class B: 92 def h(...): pass 93 94 # module N 95 96 ... 97 98 # module N.P 99 100 class C: 101 def k(...): pass 102 }}} 103 }}}} 104 105 == Referencing the Structure == 106 107 Each part of the structure is catalogued using an '''object path''', 108 indicating its location in the structure hierarchy, and a reference indicating 109 its nature and origin. For example: 110 111 || '''Object Path''' || '''Reference''' || '''Explanation''' || 112 || `M.A` || `<class>:M.A` || The definition of class `A` in module `M` || 113 || `O.A` || `<class>:M.A` || A reference to `M.A`, a class || 114 || `N.P.C.k` || `<function>:N.P.C.k` || The definition of method `k` in class `C` of module `N.P` || 115 || `O.k` || `<function>:N.P.C.k` || A reference to `N.P.C.k`, a function || 116 || `O.values` || `<instance>:__builtins__.list.list` || An object identified as an instance of class `__builtins__.list.list` || 117 || `__main__.M` || `<module>:M` || A reference to module `M` || 118 || `__main__.counter` || `<var>` || An undetermined object called `counter` in the `__main__` module || 119 120 The reference therefore expresses the '''kind''' of object (class, function, 121 instance, module or undetermined variable), possibly accompanied by an object 122 type, and also possibly accompanied by an alias indicating where the reference 123 was obtained. 124 125 == Classes == 126 127 Classes are regarded as statically-defined objects, meaning that they are only 128 evaluated once and must not be defined within conditional sections or within 129 functions. Base classes must be expressed using readily-identifiable class 130 names, since any potential ambiguity or uncertainty with the identity of base 131 classes could result in a class inheritance hierarchy that is effectively 132 dynamic. 133 134 When '''instantiated''', classes provide '''instances''' that provide the 135 attributes of each class's namespace plus any '''inherited''' attributes from 136 base classes that would not be provided by the class itself. In addition, 137 instances provide their own instance attributes. 138 139 == Functions == 140 141 Functions are regarded as statically-defined objects, but they may be defined 142 either with names within other named functions or as '''lambdas''' (functions 143 without names) within named functions or other lambdas. Thus, unlike classes, 144 functions may be defined once but replicated many times, each time with 145 different accompanying state information. Such state information needs to be 146 provided via default parameters: it is not detected and propagated 147 automatically. Closures are not supported: any state from enclosing scopes 148 must be supplied at the point of definition of a function; it is not acquired 149 from outer functions by name. 150 151 {{{#!python numbers=disable 152 def outer(a): 153 b = 2 154 def inner(c, a=a, b=b): 155 # a initialised using default from outer scope 156 # b also initialised using default from outer scope 157 return a, b, c 158 b = 4 159 160 outer(1)(3) # returns (1, 2, 3) not (1, 4, 3) 161 }}} 162 163 === Lambdas === 164 165 Lambdas are given special names for the purposes of identification within the 166 program structure, being named relative to the scope in which they are 167 defined. For example, the first lambda appearing within module `N` would have 168 an object path of `N.$l0`, and a subsequent lambda within the same scope would 169 have an object path of `N.$l1`. Lambdas may appear within classes and 170 functions, including lambdas themselves. For example: 171 172 {{{#!python numbers=disable 173 def f(x): 174 return lambda y, x=x: lambda z, x=x, y=y: (x, y, z) 175 }}} 176 177 Here, within a module `M`, the outer lambda would have the object path 178 `M.f.$l0` whereas the inner lambda would have the object path `M.f.$l0.$l0`.