Разбор скрипта, написанного на языке python.

Скачать данный скрипт можно здесь. Скрипт не требует указания дополнительных параметров для запуска и далее действует в соответствии с командами пользователя.
Думаю, что логичнее будет разбирать скрипт в порядке его написания, а не в порядке следования строк в уже готовом скрипте. Для того, чтобы проще соотносить описание со скриптом, я привожу номера строк. Итак, начнем.
На самом деле, эта программа не решает никакую важную задачу, а была написана просто как упражнение для использования классов. Идея - создать класс диснеевских принцесс, которые будут как-то взаимодействовать друг с другом. Для начала необходимо придумать какие именно атрибуты и методы будут у наших принцесс. Какие атрибуты могут быть у объекта "принцесса"? Ну конечно же, у принцессы есть имя и платье (для упрощения мы будем различать только цвет платья). Еще известно, что принцесса может быть запрятана в высокой башне или в замке чудовища, а может поехать на бал. Поэтому важный атрибут принцессы - ее координата. Ну и, естественно, самый важный атрибут принцессы - ее принц. Фух, вроде бы, с атрибутами разобрались. Теперь мы уже можем создать класс и написать его инициализирующую функцию:

11|class Princess: # it's Disney Princesses
12|    name="Name"
13|    dresscolor="color"
14|    coordinate=0
15|    prince="Prince"
16|
17|    def __init__(self, n, d, c, p):
18|        self.name=n
19|        self.dresscolor=d
20|        self.coordinate=c
21|        self.prince=p
Инициализирующая функция позволит нам легко задавать объекты созданного класса. Теперь нам не придется специально присваивать значение каждого атрибута для каждого объекта, а можно будет просто перечислить все атрибуты при задании объекта. Давайте создадим наших принцесс:
47|#There are Disney Princesses:
48|ariel=Princess("Ariel", "blue", 0, "Eric")
49|belle=Princess("Belle", "gold", 1, "Adam")
50|cinderella=Princess("Cinderella", "lightblue", 2, "Philip")
51|jasmin=Princess("Jasmin", "lightblue", 3, "Aladdin")
52|rapunzel=Princess("Rapunzel", "purple", 4, "Flynn")
53|snow_white=Princess("Snow White", "yellow", 5, "Ferdinand")
54|tiana=Princess("Tiana", "green", 6, "Navin")
Внимательный читатель заметит, что мы создали не все 10 принцесс, а только 7. Но это небольшая проблема, потому что всегда можно точно так же добавить остальных трех.
Теперь у нас есть отличный класс, в котором уже есть довольно много объектов. Но не хватает методов. Ведь должно же быть что-то, что принцессы будут делать. Ну, во-первых, принцессы могут перемещаться. Не все же им сидеть в башне, дрожа от страха перед злым драконом. А если принцессы могут путешествовать по своему миру, то они могут и встречаться. Итак, зададим метод перемещения:
39|    def travel(self, username):
40|        """This function change coordinate and dress color of princess.
41|        It gets username to communicate with him."""
42|        c=input("Chere %s, I can't choose where to go today. Could you tell any number, please, to help me make a choise? " %username)
43|        print ("Merci beaucoup! You're so cute!")
44|        self.coordinate=c%7
45|        self.dresscolor=raw_input("Oh, no... I don't know, which dress should I wear. Could you tell me a color? ")
Как мы видим, принцессе тяжело самой выбрать, куда пойти и какой наряд надеть. Я думаю, будет хорошо, если пользователь поможет в этом нашим принцессам. Обратите внимание, как мы присваиваем координату принцессе. Мы берем остаток от деления на 7 того числа, которое ввел пользователь. Это сделано для того, чтобы принцессы встречались как можно чаще. У нас есть 7 принцесс, а теперь мы сделали так, что разных координат тоже может быть только 7. Теперь наши принцессы будут встречаться в 6 случаях из 7.
Теперь зададим метод встречи двух принцесс:
23|    def meeting(self, princess):
24|        """This function models reaction of princess when she meets other princess.
25|        It gets meeting princess and checks dresses of both princesses and works it two different ways
			when dresses are similar, or they are different"""
26|        if self.dresscolor==princess.dresscolor: #Dresses are similar. It's very bad for princesses.
27|            print ("Wow, it's %s! How nice..... Ooooooooooooooops! I have the same dress with %s!!!!!!!!" %(princess.name, princess.name))
28|            print ("%s: -Oh my God! What a shame!" %princess.name[0])
29|            self.coordinate=random.randint(0,6) #Princesses run away
30|            princess.coordinate=random.randint(0,6)
31|            self.dresscolor=raw_input("I have to change my dress! Please, please, please, tell me a color! ")
32|            search_neighbor(self)
33|        else: #Dresses are different, so princesses can talk to each other.
34|            print ("Do you see..? It's %s here. Wait a minute, please, I want to talk to her." %princess.name)
35|            print ("%s: -Bonjour, %s! How are you? Do you like my %s dress?" %(self.name[0], princess.name, self.dresscolor))
36|            print ("%s: -Bonjour, ma chere! You look wonderful!
					You know, I'm so happy today, I've met my prince %s!" %(princess.name[0], princess.prince))
37|            print ("%s: -Oh, I'm so glad for you! But I need to go now. See you at the ball!" %self.name[0])
Что происходит, когда встречаются две принцессы? Конечно же, наши принцессы - крайне милые существа, поэтому они радостно делятся простыми девичьими радостями, делают друг другу комплементы и прощаются до следующей встречи на балу.
Но что, если у принцесс одинаковые платья? Всем принцессам известно, что ничего хуже, чем увидеть свое платье на другой принцессе, быть не может. Поэтому если встречаются две принцессы в одинаковых платьях, то они тут же разбегаются в разные стороны, куда глаза глядят. Для того, чтобы принцессы разбежались, присваиваем им произвольную координату. Для этого в самом начале необходимо подключить модуль random:
09|import random
После того, как принцессы разбежались, им необходимо переодеться, чтобы больше такой неприятности с ними не происходило. И тут принцесса опять просит помощи у пользователя. Теперь принцесса снова готова встречаться с другими принцессами.
Сейчас в нашем методе есть еще не поясненная команда search_neighbor(self).
Эта функция не является методом класса, а является вспомогательной функцией в программе. Она-то и определяет, встретилась ли наша принцесса с какой-нибудь другой. Для того, чтобы задать эту функцию, нам необходимо создать словарь с координатами принцесс. Такой словарь позволит в дальнейшем находить принцессу по координате:
57|coorlist={ariel.coordinate:ariel, belle.coordinate:belle, cinderella.coordinate:cinderella,
		jasmin.coordinate:jasmin, rapunzel.coordinate:rapunzel, snow_white.coordinate:snow_white, tiana.coordinate:tiana}
Теперь зададим функцию поиска втретившихся принцесс:
68|def search_neighbor(princess):
69|    """This function define, if our princess has the similar coordinate with other princess.
70|    If princesses have the same coordinate, they meet each other. If princess doesn't meet somebody, she asks to change coordinate."""
71|    if coorlist[princess.coordinate]==princess:
72|        princess.coordinate=input("There are nobody here. I feel so sad and lonely... Give me, please, another number: ")
73|        search_neighbor(princess)
74|    else:
75|        princess.meeting(coorlist[princess.coordinate])
76|    return princess
Как мы видим, функция крайне проста. Она проверяет, есть ли у какой-то еще принцессы та же координата, что и у нашей. Если нет - то принцесса просит поменять ей координату. Если есть - две принцессы встречаются, а как - мы уже знаем.
Теперь уже появилось ощущение, что мы почти написали программу. У нас есть класс принцесс, которые могут перемещаться, переодеваться и встречать друг друга. Осталось придумать, как именно все это будет происходить.
Проще всего сделать так: пользователь будет выбирать одну принцессу, которой он сможет играть, и все остальные принцессы будут взаимодействовать с выбранной.
Собственно, теперь мы напишем саму программу, которая будет вызывать уже готовые функции:
78|print ("Welcome to the world of Disney Princesses! We are Ariel, Belle,
				Cinderella, Jasmin, Rapunzel, Tiana and Snow White. And we're very glad to see you!")
79|username=raw_input ("Please, enter your name: ")
80|name_princess=raw_input ("%s, you can choose any of us. But only ONE of us, so think twice and type the name.
	If you're scared and can't make a choice just type \"exit\" " %username)
81|if name_princess=="exit":
82|    print ("Oh, that's so sad... But don't worry, you can try again later if you want. Bye-bye!")
83|    exit()
84|else:
85|    princess=check(name_princess)
Теперь нам необходимо проверить, какую принцессу выбрал пользователь. Для этого нам понадобится словарь с именами принцесс и еще одна вспомогательная функция:
56|namelist={"Ariel":ariel,"Belle":belle,"Cinderella":cinderella,"Jasmin":jasmin,"Rapunzel":rapunzel,"Snow White":snow_white,"Tiana":tiana}
59|def check(princess):
60|    """This function define choosen princess."""
61|    if princess not in namelist:
62|        princess=raw_input ("There are no %s, try again, please: " %princess) #Wrong name of princess
63|        princess=check(princess)
64|    else:
65|        princess=namelist[princess]
66|    return princess
Функция возвращает объект - конкретную принцессу, если пользователь ввел имя существующей принцессы, либо просит ввести имя еще раз. После того как программа определила, какую принцессу выбрал пользователь, она выполняет следующие команды:
86|print ("I'm so happy you chose me! I think, we should take a walk.")
87|princess.travel(username)
88|search_neighbor(princess)
89|print("Thank you, %s! It was a nice promenade. But it's too late, I think we have to leave. See you later." %username)
Итак, наша программа готова! Давайте посмотрим, как она работает:

В процессе этого, довольно поверхностного, разбора я заметила несколько моментов, которые можно было бы улучшить в этой программе.
Во-первых, создание словарей с именами и координатами принцесс - довольно искусственная вещь. Наверняка, это можно сделать более естественным образом, используя поиск объектов в классе по определенным параметрам.
Во-вторых, при задании координат нужно брать остаток при делении не на 7, а на количество принцесс в классе. Иначе, этот момент придется каждый раз менять вручную, если мы захотим, например, добавить в наш класс еще несколько объектов.
В-третьих, не очень хорошо то, что метод meeting использует функцию программы search_neighbor(princess). Получается, что данный класс не может быть использован без этой функции. Можно подумать о том, как фунцкию search_neighbor(princess) сделать методом класса.
Тем не менее, несмотря на простоту этой программы, она взаимодействует с пользователем и может действовать различными способами, в зависимости от действий пользователя.


© Наталья Ланина
e-mail: n.lanina@fbb.msu.ru

последний раз обновлялось: 30.12.13