【问题标题】:Python - Classes and OOP BasicsPython - 类和 OOP 基础
【发布时间】:2012-04-04 04:16:44
【问题描述】:

我不完全理解类。我已经阅读了 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 在 else 上重复,并且在调用时返回其他房间(这将是类),那就太棒了。

另外,我对__init__ 非常不稳定,我仍然不确定它的目的是什么。每个人都一直告诉我它“初始化”了,我相信它确实如此,但这似乎并没有帮助我的大脑。

【问题讨论】:

    标签: python oop


    【解决方案1】:

    函数与类非常不同。看起来您使用了一个函数,只是将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'
    

    漂亮。但是,如果您希望不同的房间具有不同的功能,这并不是那么有用,所以让我们创建一个 子类子类从其超类继承所有功能,但您可以添加更多功能或覆盖超类的功能。

    让我们想想我们想对房间做什么:

    我们想与房间互动。

    我们如何做到这一点?

    用户输入一行得到响应的文本。

    它的响应方式取决于房间,所以让我们使用一个名为 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让我们也制作一个红色房间。

    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'
    

    读者练习:将代码添加到WhiteRoominteract,让您回到红色房间。

    现在我们已经一切正常,让我们把它们放在一起。使用我们所有房间的新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()
    

    这是对课程的基本介绍以及如何将其应用于您的情况。

    【讨论】:

    • Ball 不应该是一个类。经验法则:如果它只有两个方法,其中一个是__init__,您应该使用一个函数和functools.partial 将函数绑定到一些数据。此处介绍的其他类也是如此。 Python 不是 Java!我在这里看到的唯一应该是一个类是游戏本身,你使用模块全局状态来代替?
    • 在用户练习部分,我试图让从白色房间到红色房间成为可能。但是我不能。我在行中添加了 "if "x": current_room = red_room" 当前房间变量没有改变。但是,如果我执行以下操作:“if "x" in line: print "this"" 它可以工作。谢谢你的文章。非常有帮助!
    • @Niklas:是的;游戏状态真的应该在一个类中;然而,我试图让它尽可能简单,我觉得将游戏状态设为一个类可能会使我的答案更加混乱。其次,也许其中一些东西不应该是类,但鉴于我试图演示如何使用类,我认为使用它们是合理的。此外,我认为有人可以想到其他方法和数据来添加到类中。
    • @icktoofay:是的,我认为你说得有道理 :) +1 详细解释。
    【解决方案2】:

    我相信你以前听过这一切,但我会试一试。

    类是一种将一堆函数和变量组合成一个对象的方法。当您深入了解它时,这只是一种将所有内容组织成有意义的组的方法。让事情更容易理解、调试、扩展或维护是有好处的,但基本上它只是一种让你的思维模型更明确的方法。

    您的代码看起来像是在尝试将整个程序编写在一个“对象”中(实际上,您只是编写了一个错误的函数)。

    请考虑这个。

    想想你的心智模型,房间里有门,里面有白板。门有颜色。此外,白板上可以写一些文字。我们让它保持简单。

    对我来说,这意味着 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 和 Whiteboard 对象。我传递给构造函数Room(parameter1, parameter2) 的参数被传递给init 函数——你可以看到我正在使用它来设置门颜色和白板上的一些文本(可选)。还要注意,“属于”对象的变量是用self 引用的——这个引用是作为所有类函数的第一个参数传入的(稍后在扩展类和其他更高级的东西时变得更加重要)。

    【讨论】:

      【解决方案3】:

      我从Learning Python by Mark Lutz 了解了 Python 中的 OOPS。它是理解 Python 概念的综合资源,尤其是用于编写 Pythonic 方式的代码。

      为了您的在线参考,我喜欢来自this 站点的教程。 通过这个post,它将帮助您进行初始化。 Python 中的 OOP 非常容易理解和实现。起初看起来令人生畏,但在编写了一些基本的 OOP 代码之后就轻而易举了。 享受学习..

      【讨论】:

        【解决方案4】:

        你真的很遥远。

        很抱歉,但这几乎无法挽救。

        据我所知,你想要一个房间类之类的东西,例如:

        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"
        

        然后你可以像这样制作一个特定的房间,比如白色房间:

        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."
        

        那么你必须这样做才能运行游戏:

        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()
        

        这是我使用类将您的 sn-p 变成实际游戏的最佳尝试。

        【讨论】:

          【解决方案5】:

          一开始,面向对象编程可能是一件非常有趣的事情,真正了解它的唯一方法是花时间做大量的阅读和练习。一个很好的起点将是在这里。 http://www.voidspace.org.uk/python/articles/OOP.shtmlhttp://wiki.python.org/moin/BeginnersGuide/Programmers

          【讨论】:

            【解决方案6】:

            类圆():

            pi = 3.14
            
            def __init__(self,radius=1):
                
                self.radius = radius
                self.area = radius*radius*self.pi
            
            def get_circrumference(self):
                return self.radius* self.pi*2
                
            

            结果: 圆(23)

            my_circle = 圆(30)

            my_circle.pi = 3.14

            my_circle.radius = 30

            my_circle.get_circrumference() = 118.4

            my_circle.area = 2826.0

            帮助(圆圈)= ma​​in 模块中的 Circle 类帮助:

            类 Circle(builtins.object) |圆(半径=1) |
            |此处定义的方法: |
            | 初始化(自我,半径=1) |初始化自己。请参阅 help(type(self)) 以获取准确的签名。 |
            | get_circumference(自我) |
            | -------------------------------------------------- -------------------- |此处定义的数据描述符: |
            | 听写 |实例变量的字典(如果已定义) |
            | 弱引用 |对象的弱引用列表(如果已定义) |
            | -------------------------------------------------- -------------------- |此处定义的数据和其他属性: |
            | pi = 3.14

            【讨论】:

            • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
            猜你喜欢
            • 2015-12-18
            • 2011-07-05
            • 2014-06-19
            • 2012-05-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-24
            相关资源
            最近更新 更多