Давайте рассмотрим один практический пример.
Допустим, мы программируем навигацию по меню для игры. Мы хотим хранить для каждого пункта меню
- Название записи
- В другое меню мы попадем после его нажатия.
- Действие, которое будет выполняться при нажатии на меню.
Когда нажимается пункт меню, мы активируем действие пункта меню и затем переходим к следующему меню. Таким образом, наше меню будет простым списком словарей, например так:
options,start_menu,about = [],[],[]
def do_nothing(): pass
about += [
{'name':"copyright by...",'action':None,'menu':about},
{'name':"back",'action':do_nothing,'menu':start_menu}
]
options += [
{'name':"volume up",'action':volumeUp,'menu':options},
{'name':"save",'action':save,'menu':start_menu},
{'name':"back without save",'action':do_nothing,'menu':start_menu}
]
start_menu += [
{'name':"Exit",'action':f,'menu':None}, # no next menu since we quite
{'name':"Options",'action':do_nothing,'menu':options},
{'name':"About",'action':do_nothing,'menu':about}
]
Посмотрите, как about
является циклическим:
>>> print about
[{'action': None, 'menu': [...], 'name': 'copyright by...'},#etc.
# see the ellipsis (...)
При нажатии на пункт меню мы запускаем следующую функцию нажатия:
def menu_item_pressed(item):
log("menu item '%s' pressed" % item['name'])
item['action']()
set_next_menu(item['menu'])
Теперь, если бы у нас не было циклических структур данных, у нас не было бы пункта меню, который бы указывал на себя, и, например, после нажатия функции увеличения громкости нам пришлось бы оставить опции меню.
Если циклические структуры данных были бы невозможны, нам придется реализовать их самостоятельно, например, пункт меню будет:
class SelfReferenceMarkerClass: pass
#singleton global marker for self reference
SelfReferenceMarker = SelfReferenceMarkerClass()
about += [
{'name':"copyright by...",'action':None,'menu':srm},
{'name':"back",'action':do_nothing,'menu':start_menu}
]
функция menu_item_pressed
будет:
def menu_item_pressed(item):
item['action']()
if (item['menu'] == SelfReferenceMarker):
set_next_menu(get_previous_menu())
else:
set_next_menu(item['menu'])
Первый пример немного приятнее, но да, не поддержка собственных ссылок - не такая уж большая проблема, ИМХО, поскольку это ограничение легко преодолеть.
Пример меню подобен графу с собственными ссылками, где мы храним граф в виде списков указателей вершин (каждая вершина является списком указателей на другие вершины). В этом примере нам были нужны собственные ребра (вершина, указывающая на себя), поэтому поддержка python для циклических структур данных полезна.