2012-04-04 8 views
10

Я не совсем понимаю классы. Я прочитал документацию python и несколько других учебников. Я получаю основной смысл, но не понимаю нюанса. Например, в моем коде здесь:Python - Классы и основы ООП

class whiteroom(): 
    """ Pick a door: red, blue, green, or black. """ 

    do = raw_input("> ") 

    if "red" in do: 
     print "You entered the red room." 

    elif "blue" in do: 
     print "You entered the blue room." 

    elif "green" in do: 
     print "You entered the green room." 

    elif "black" in do: 
     print "You entered the black room." 

    else: 
     print "You sit patiently but slowly begin to stave. You're running out of time." 
     return whiteroom() 

game = whiteroom() 
game 

(оригинал codepad)

Я хотел бы вернуть класс whiteroom. Что либо невозможно, либо не сделано правильно. Если вы могли бы прояснить, как вернуть класс или как «связать» два класса вместе, чтобы повторять белые пробелы в других и других комнатах (которые были бы классами), возвращались при вызове, которые были бы удивительными.

Также я очень шаткий на __init__ и до сих пор не уверен, в чем его цель. Все говорят мне, что это «инициализирует», что я уверен, что это так, но это, похоже, не помогает моему мозгу.

ответ

37

Функции сильно отличаются от классов. Похоже, вы взяли функцию и только что изменили def на class. Я думаю, что в основном работает в вашем случае, но это не то, как должны идти классы.

Классы содержат функции (методы) и данные. Например, у вас есть мяч:

class Ball(object): 
    # __init__ is a special method called whenever you try to make 
    # an instance of a class. As you heard, it initializes the object. 
    # Here, we'll initialize some of the data. 
    def __init__(self): 
     # Let's add some data to the [instance of the] class. 
     self.position = (100, 100) 
     self.velocity = (0, 0) 

    # We can also add our own functions. When our ball bounces, 
    # its vertical velocity will be negated. (no gravity here!) 
    def bounce(self): 
     self.velocity = (self.velocity[0], -self.velocity[1]) 

Теперь у нас есть Ball класса. Как мы можем его использовать?

>>> ball1 = Ball() 
>>> ball1 
<Ball object at ...> 

Это не очень полезно. Данные могут быть полезными:

>>> ball1.position 
(100, 100) 
>>> ball1.velocity 
(0, 0) 
>>> ball1.position = (200, 100) 
>>> ball1.position 
(200, 100) 

Хорошо, круто, но в чем преимущество над глобальной переменной? Если у вас есть еще один Ball экземпляр, он будет оставаться независимыми:

>>> ball2 = Ball() 
>>> ball2.velocity = (5, 10) 
>>> ball2.position 
(100, 100) 
>>> ball2.velocity 
(5, 10) 

И ball1 остается независимым:

>>> ball1.velocity 
(0, 0) 

что теперь об этом bounce метода (функции в классе) мы определили?

>>> ball2.bounce() 
>>> ball2.velocity 
(5, -10) 

bounce метод вызвал его модифицировать velocity данные себе. Опять же, ball1 не тронули:

>>> ball1.velocity 

Применение

Мяч аккуратно и все, но большинство людей не имитируя, что. Вы делаете игру. Давайте думать о том, какие вещи, которые мы имеем:

  • Комната самая очевидная вещь, которую мы могли бы иметь.

Итак, давайте сделаем комнату. Номера имеют имена, поэтому мы будем иметь некоторые данные для хранения, что:

class Room(object): 
    # Note that we're taking an argument besides self, here. 
    def __init__(self, name): 
     self.name = name # Set the room's name to the name we got. 

И давайте сделаем его экземпляр:

>>> white_room = Room("White Room") 
>>> white_room.name 
'White Room' 

элегантным. Это оказывается не таким полезным, если вы хотите, чтобы разные комнаты имели разные функциональные возможности, поэтому давайте сделаем подкласс . A подкласс наследует всю функциональность от своего суперкласса, но вы можете добавить больше функциональности или переопределить функциональность суперкласса.

Давайте подумаем о том, что мы хотим сделать с номерами:

Мы хотим взаимодействовать с номерами.

И как мы это сделаем?

Пользователь вводит в текстовую строку, на которую реагирует.

Как это ответил бы, зависит от помещения, так что давайте сделать комнату справиться, что с помощью метода под названием interact:

class WhiteRoom(Room): # A white room is a kind of room. 
    def __init__(self): 
     # All white rooms have names of 'White Room'. 
     self.name = 'White Room' 

    def interact(self, line): 
     if 'test' in line: 
      print "'Test' to you, too!" 

Теперь давайте попробуем взаимодействовать с ним:

>>> white_room = WhiteRoom() # WhiteRoom's __init__ doesn't take an argument (even though its superclass's __init__ does; we overrode the superclass's __init__) 
>>> white_room.interact('test') 
'Test' to you, too! 

Ваш оригинальный пример показал перемещение между комнатами. Давайте используем глобальную переменную, называемую current_room, чтобы отслеживать, в какой комнате мы находимся. Давайте также сделаем красную комнату.

1. Здесь есть лучшие варианты, кроме глобальных переменных, но я собираюсь использовать их для простоты.

class RedRoom(Room): # A red room is also a kind of room. 
    def __init__(self): 
     self.name = 'Red Room' 

    def interact(self, line): 
     global current_room, white_room 
     if 'white' in line: 
      # We could create a new WhiteRoom, but then it 
      # would lose its data (if it had any) after moving 
      # out of it and into it again. 
      current_room = white_room 

Теперь давайте попробуем, что:

>>> red_room = RedRoom() 
>>> current_room = red_room 
>>> current_room.name 
'Red Room' 
>>> current_room.interact('go to white room') 
>>> current_room.name 
'White Room' 

Упражнение для читателя: Добавьте код WhiteRoom «s interact, что позволяет вернуться в красную комнату.

Теперь, когда у нас все работает, давайте все вместе. С нашими новыми данными name во всех номерах мы также можем отобразить текущую комнату в строке!

def play_game(): 
    global current_room 
    while True: 
     line = raw_input(current_room.name + '> ') 
     current_room.interact(line) 

Вы также можете захотеть сделать функцию сброса игры:

def reset_game(): 
    global current_room, white_room, red_room 
    white_room = WhiteRoom() 
    red_room = RedRoom() 
    current_room = white_room 

Поместите все определения классов и эти функции в файл, и вы можете играть в командной строке, как это (при условии, что они находятся в mygame.py):

>>> import mygame 
>>> mygame.reset_game() 
>>> mygame.play_game() 
White Room> test 
'Test' to you, too! 
White Room> go to red room 
Red Room> go to white room 
White Room> 

чтобы иметь возможность играть в игру, просто запустив сценарий Python, вы можете добавить это в нижней части:

def main(): 
    reset_game() 
    play_game() 

if __name__ == '__main__': # If we're running as a script... 
    main() 

И это базовое введение в классы и способы применения его к вашей ситуации.

+2

Этот 'Ball' не должен быть классом. Правило большого пальца: если у него есть только два метода, один из которых - '__init__', вы должны использовать функцию и функцию functools.partial для привязки функции к некоторым данным. То же самое для других классов, представленных здесь. Python - это не Java! Единственное, что я вижу здесь, что * должен быть классом, это сама игра, для которой вместо этого вы используете модульное глобальное состояние? –

+0

В разделе пользовательских упражнений я попытался перейти из белой комнаты в красную комнату. Но я не могу. Я добавил «if» x «in line: current_room = red_room» Текущая переменная комнаты не изменяется. Однако, если я делаю что-то вроде: «если« х »в строке: напечатайте« это », это работает. Спасибо за ваше сообщение. Это было очень полезно! –

+0

Nevermind Я понял это! Еще раз спасибо за вашу помощь :) –

1

Объектно-ориентированное программирование может быть очень забавным, чтобы понять сначала, единственный способ действительно хэш через него - фактически потратить время, чтобы сделать много чтения и практики. Хорошее место для начала было бы здесь. http://www.voidspace.org.uk/python/articles/OOP.shtml и http://wiki.python.org/moin/BeginnersGuide/Programmers

5

Я уверен, что вы все это слышали раньше, но я отдам это.

Классы - это способ группировки пучка функций и переменных в один объект. Когда вы доберетесь до него, это просто способ организовать все в группы, которые имеют смысл. Есть преимущества по пути, чтобы облегчить понимание, отладку, расширение или поддержку, но в основном это просто способ сделать что-то более определенное в вашей ментальной модели.

Ваш код выглядит так, будто вы пытаетесь написать всю свою программу внутри «объекта» (на самом деле у вас есть неправильно написанная функция).

Рассмотрите это вместо этого.

Подумайте о своей ментальной модели комнат, в которых есть двери для них и доски. Двери имеют цвет. Кроме того, на досках есть текст, написанный на них. Мы оставим его там, чтобы быть простым.

Для меня это предполагает 3 разных объекта - объект двери, который имеет строку для цвета, объект доски, который имеет строку для текста, и объект комнаты, который имеет дверь и доску.

Рассмотрим следующий код:

class Door(object): 
    def __init__(self, color): 
     self.color = color 

class Whiteboard(object): 
    def __init__(self, default_text=''): 
     self.text = '' 
     self.write_text(default_text) 

    def write_text(self, text): 
     self.text += text 

    def erase(self): 
     self.text = '' 


class Room(object): 
    def __init__(self, doorcolor, whiteboardtext=''): 
     self.whiteboard = Whiteboard(whiteboardtext) 
     self.door = Door(doorcolor) 




# make a room with a red door and no text on the whiteboard 
room1 = Room('red') 

# make a room with a blue door and 'yeah, whiteboard' on the whiteboard 
room2 = Room('blue', 'yeah, whiteboard') 

# make a room with a green door 
room3 = Room('green') 



# now I can play around with my 'rooms' and they keep track of everything internally 

print 'room 1 door color: ' + room1.door.color 
print 'room 2 door color: ' + room2.door.color 


# all my rooms have a door and a whiteboard, but each one is different and self contained. For example 
# if I write on room 1's whiteboard, it doesn't change anything about room 3s 

print 'room1 whiteboard: ' + room1.whiteboard.text 
print 'room2 whiteboard: ' + room2.whiteboard.text 
print 'room3 whiteboard: ' + room3.whiteboard.text 

print '-- changeing room 1 whiteboard text --' 

room1.whiteboard.write_text('oop is really helpful') 


print 'room1 whiteboard: ' + room1.whiteboard.text 
print 'room2 whiteboard: ' + room2.whiteboard.text 
print 'room3 whiteboard: ' + room3.whiteboard.text 

INIT функция является то, что вызывается, когда вы инициализации 'новый экземпляр вашего класса. В примере я делаю 3 объекта Room, каждый из которых создает объект Door and Whiteboard внутри. Параметры, которые я передаю в конструктор Room(parameter1, parameter2), передаются в функции init - вы можете видеть, что я использую это, чтобы установить цвет двери и, возможно, некоторый текст на доске. Также обратите внимание, что переменные, которые «принадлежат» объектам, ссылаются на self - эта ссылка - это то, что передается как первый параметр для всех функций класса (и становится более важным позже, когда вы расширяете классы и другие более продвинутые вещи).

2

Ну, я понял OOPS в Python от Learning Python by Mark Lutz. Это всеобъемлющий источник для понимания концепций Python, особенно для кода Pythonic.

Для вашей онлайн-ссылки мне нравятся учебные материалы с сайта this. Пройдите через это post, это поможет вам с init. ООП в Python очень легко понять и реализовать. Сначала это кажется сложным, но его легкий ветерок после программирования некоторых базовых кодов ООП. Наслаждайтесь обучением.

2

Вы действительно далеко.

Извините, что вы говорите, но это едва спасено.

Из того, что я могу сказать, вы хотите что-то вроде класса номера, например:

class Room(object): 
    ''' A generic room ''' 
    def __init__(self): 
     self.choices = None 
     self.enter() 
    def enter(self): 
     ''' Enter the room, to be filled out in subclass ''' 
     pass 
    def print_choices(self): 
     '''You are stuck bro''' 
     print "You are stuck bro" 

Затем вы можете сделать определенный номер вроде whiteroom как так:

class Whiteroom(Room): 
    ''' A white room ''' 
    def __init__(self): 
     self.choices = ["red", "blue", "green", "black"] 
     self.enter() 
    def enter(self): 
     print "You sit patiently, but slowly begin to starve. You're running out of time." 
    def print_choices(self): 
     print "You can choose from the following rooms:" 
     print self.choices 

class Blackroom(Room): 
    ''' A black room ''' 
    def enter(self): 
     print "It's really dark in here. You're out of time." 

class Redroom(Room): 
    ''' A red room ''' 
    def __init__(self): 
     self.choices = ["black", "blue", "green", "white"] 
     self.enter() 
    def enter(self): 
     print "It's getting hot in here. So take off all your clothes." 
    def print_choices(self): 
     print "You can choose from the following rooms:" 
     print self.choices 

class Blueroom(Room): 
    ''' A blue room ''' 
    def __init__(self): 
     self.choices = ["black", "red", "green", "white"] 
     self.enter() 
    def enter(self): 
     print "It's nice and cool in here. Stay awhile if you want." 
    def print_choices(self): 
     print "You can choose from the following rooms:" 
     print self.choices 

class Greenroom(Room): 
    ''' A green room ''' 
    def __init__(self): 
     self.choices = ["black", "red", "blue", "white"] 
     self.enter() 
    def enter(self): 
     print "You won." 

Тогда вы» d сделать это, чтобы запустить игру:

print "Type 'quit' to quit" 
print "Type 'choices' to see what your choices are" 

current_room = Whiteroom() 
done = False 
while (not done): 
    entry = raw_input("> ") 
    if entry == "quit": 
     done = True 
    if "choices" in entry: 
     current_room.print_choices() 
    if current_room.choices: 
     if entry in current_room.choices:  
      if "white" in entry: 
       current_room = Whiteroom() 

      if "black" in entry: 
       current_room = Blackroom() 

      if "red" in entry: 
       current_room = Redroom() 

      if "green" in entry: 
       current_room = Greenroom() 
       done = True 

      if "blue" in entry: 
       current_room = Blueroom() 

Это моя лучшая попытка превратить ваш фрагмент в ac игры, используя классы.