[Tutor] questions when define a class

Peter Otten __peter__ at web.de
Tue Apr 15 15:46:39 CEST 2014

```Qianyun Guo wrote:

> Hi all, I am trying to get a suffix tree from a string. I use three
> classes, Node, Edge, SuffixTree. I have two questions when implementing:
>
> 【1】
>
>>>> a = Edge(1,2,3,4)
>
>>>> a.length
>
> 1
> if I remove  '@property' in my code, it returns as below:
>
>>>> a = Edge(1,2,3,4)
>
>>>> a.length
>
> <bound method Edge.length>
>
>>>> a.length()
>
> 1
>
>
>
> I don't really understand the differences w/ @property, and the
> differences of a.length and a.length(), could you explain?

Properties are a way to calculate attributes:

>     @property
>     def length(self):
>         return self.last_char_index - self.first_char_index

In client code

obj.length

looks like an attribute, but does a calculation under the hood. This is
particularly useful to keep a changing interface compatible to prior
versions:

version 1, everybody uses cartesian coordinates:

class Point:
def __init__(self, x, y):
self.x = x
self.y = y

version 2, polar coordinates are so much better ;)

class Point:
def __init__(self, r, phi):
self.r = r
self.phi = phi
@property
def x(self):
return self.r * math.cos(self.phi)
@property
def y(self):
return self.r * math.sin(self.phi)

Thanks to properties our new point can be passed to functions that expect
cartesian coords. Without properties we'd either end up writing a trivial
wrapper

def get_x(self):
return self.x

for every attribute (the Java way) and never use attributes directly or we'd
have to change all occurences of point.x to point.x().

> 【2】
>
> In SuffixTree, I define two functions, _get_str_from_edge,
> _get_str_from_node, the latter depend on the first one (please see my
> code).  Then I have this problem:
>
>>>> a = SuffixTree('abcd')
>
>>>> a._get_str_from_edge(a.edges[(0,1)])
>
> 'abcd\$'
>
>>>> a._get_str_from_node(0,1)
>
> TypeError: _get_str_from_edge() takes exactly 2 arguments (3 given)
>
> Could you tell me what's wrong here?

>     def _get_str_from_node(self, source_node_index, dest_node_index):
>         return self._get_str_from_edge(self,
>         self.edges[(source_node_index,
> \
>                 dest_node_index)])

self._get_str_from_edge

gives you a "bound method", i. e. one that already knows about self. Invoke
it as

return self._get_str_from_edge(
self.edges[(source_node_index,
dest_node_index)])

By the way, the backslash is not necessesary as long as there are open
parens. Preferred:

(1 + # no backslash
2)

Obsolete alternative:
1 + \
2

```