Segment.__init__(self, header, stream)
         Dynamic.__init__(self, stream, elffile, stringtable, self['p_offset'],
              self['p_filesz'] == 0)
-        self._symbol_list = None
+        self._symbol_size = self.elfstructs.Elf_Sym.sizeof()
+        self._num_symbols = None
         self._symbol_name_map = None
 
     def num_symbols(self):
         """ Number of symbols in the table recovered from DT_SYMTAB
         """
-        if self._symbol_list is None:
-            self._symbol_list = list(self.iter_symbols())
-        return len(self._symbol_list)
-
-    def get_symbol(self, index):
-        """ Get the symbol at index #index from the table (Symbol object)
-        """
-        if self._symbol_list is None:
-            self._symbol_list = list(self.iter_symbols())
-        return self._symbol_list[index]
-
-    def get_symbol_by_name(self, name):
-        """ Get a symbol(s) by name. Return None if no symbol by the given name
-            exists.
-        """
-        # The first time this method is called, construct a name to number
-        # mapping
-        #
-        if self._symbol_name_map is None:
-            self._symbol_name_map = defaultdict(list)
-            for i, sym in enumerate(self.iter_symbols()):
-                self._symbol_name_map[sym.name].append(i)
-        symnums = self._symbol_name_map.get(name)
-        return [self.get_symbol(i) for i in symnums] if symnums else None
-
-    def iter_symbols(self):
-        """ Yield all symbols in this dynamic segment. The symbols are usually
-            the same as returned by SymbolTableSection.iter_symbols. However,
-            in stripped binaries, SymbolTableSection might have been removed.
-            This method reads from the mandatory dynamic tag DT_SYMTAB.
-        """
-        tab_ptr, tab_offset = self.get_table_offset('DT_SYMTAB')
-        if tab_ptr is None or tab_offset is None:
-            raise ELFError('Segment does not contain DT_SYMTAB.')
-
-        symbol_size = self.elfstructs.Elf_Sym.sizeof()
-
-        end_ptr = None
+        if self._num_symbols is not None:
+            return self._num_symbols
 
         # Check if a DT_GNU_HASH tag exists and recover the number of symbols
         # from the corresponding hash table
         _, gnu_hash_offset = self.get_table_offset('DT_GNU_HASH')
         if gnu_hash_offset is not None:
             hash_section = GNUHashTable(self.elffile, gnu_hash_offset, self)
-            end_ptr = tab_ptr + \
-                hash_section.get_number_of_symbols() * symbol_size
+            self._num_symbols = hash_section.get_number_of_symbols()
 
         # If DT_GNU_HASH did not exist, maybe we can use DT_HASH
-        if end_ptr is None:
+        if self._num_symbols is None:
             _, hash_offset = self.get_table_offset('DT_HASH')
             if hash_offset is not None:
                 # Get the hash table from the DT_HASH offset
                 hash_section = ELFHashTable(self.elffile, hash_offset, self)
-                end_ptr = tab_ptr + \
-                    hash_section.get_number_of_symbols() * symbol_size
+                self._num_symbols = hash_section.get_number_of_symbols()
 
-        if end_ptr is None:
+        if self._num_symbols is None:
             # Find closest higher pointer than tab_ptr. We'll use that to mark
             # the end of the symbol table.
+            tab_ptr, tab_offset = self.get_table_offset('DT_SYMTAB')
+            if tab_ptr is None or tab_offset is None:
+                raise ELFError('Segment does not contain DT_SYMTAB.')
             nearest_ptr = None
             for tag in self.iter_tags():
                 tag_ptr = tag['d_ptr']
                 if tag['d_tag'] == 'DT_SYMENT':
-                    if symbol_size != tag['d_val']:
+                    if self._symbol_size != tag['d_val']:
                         # DT_SYMENT is the size of one symbol entry. It must be
                         # the same as returned by Elf_Sym.sizeof.
                         raise ELFError('DT_SYMENT (%d) != Elf_Sym (%d).' %
-                                    (tag['d_val'], symbol_size))
+                                       (tag['d_val'], self._symbol_size))
                 if (tag_ptr > tab_ptr and
                         (nearest_ptr is None or nearest_ptr > tag_ptr)):
                     nearest_ptr = tag_ptr
                         nearest_ptr = segment['p_vaddr'] + segment['p_filesz']
 
             end_ptr = nearest_ptr
+            self._num_symbols = (end_ptr - tab_ptr) // self._symbol_size
 
-        if end_ptr is None:
+        if self._num_symbols is None:
             raise ELFError('Cannot determine the end of DT_SYMTAB.')
 
+        return self._num_symbols
+
+    def get_symbol(self, index):
+        """ Get the symbol at index #index from the table (Symbol object)
+        """
+        tab_ptr, tab_offset = self.get_table_offset('DT_SYMTAB')
+        if tab_ptr is None or tab_offset is None:
+            raise ELFError('Segment does not contain DT_SYMTAB.')
+
+        symbol = struct_parse(
+            self.elfstructs.Elf_Sym,
+            self._stream,
+            stream_pos=tab_offset + index * self._symbol_size)
+
         string_table = self._get_stringtable()
-        for i in range((end_ptr - tab_ptr) // symbol_size):
-            symbol = struct_parse(self.elfstructs.Elf_Sym, self._stream,
-                                  i * symbol_size + tab_offset)
-            symbol_name = string_table.get_string(symbol['st_name'])
-            yield Symbol(symbol, symbol_name)
+        symbol_name = string_table.get_string(symbol["st_name"])
+
+        return Symbol(symbol, symbol_name)
+
+    def get_symbol_by_name(self, name):
+        """ Get a symbol(s) by name. Return None if no symbol by the given name
+            exists.
+        """
+        # The first time this method is called, construct a name to number
+        # mapping
+        #
+        if self._symbol_name_map is None:
+            self._symbol_name_map = defaultdict(list)
+            for i, sym in enumerate(self.iter_symbols()):
+                self._symbol_name_map[sym.name].append(i)
+        symnums = self._symbol_name_map.get(name)
+        return [self.get_symbol(i) for i in symnums] if symnums else None
+
+    def iter_symbols(self):
+        """ Yield all symbols in this dynamic segment. The symbols are usually
+            the same as returned by SymbolTableSection.iter_symbols. However,
+            in stripped binaries, SymbolTableSection might have been removed.
+            This method reads from the mandatory dynamic tag DT_SYMTAB.
+        """
+        for i in range(self.num_symbols()):
+            yield(self.get_symbol(i))