• Python之面向对象1


    面向对象的最主要目的是提高程序的重复使用性。Python的整个概念是基于对象的。了解OOP是进一步学习Python的关键。

    Python中的对象

    在Python中,一个对象的特征(或“你知道的事情”)也称为属性(attribute),这应该很好记。动作(或“能够对对象做的操作”)称为方法(method)。

    如果要建立一个球的Python版本或者模型(model),球就是一个对象,它要有属性和方法。

    球的属性可能包括:

    ball.color

    ball.size

    ball.weight

    这些都是关于球的描述。

    球的方法可能包括:

    ball.kick()

    ball.throw()

    ball.inflate()

    这些都是可以对球做的操作

    什么是属性

    属性就是你所知道(或者可以得出)的关于球的所有方面。球的属性就是一些信息(数字、字符串等等)。听起来很熟悉?没错,它们就是变量,只不过是包含在对象中的变量。

    可以显示:

    print ball.size

    可以为它们赋值:

    ball.color = 'green'

    可以把它们赋给常规的、不是对象的变量:

    myColor = ball.color

    还可以把它们赋给其他对象的属性:

    myBall.color = yourBall.color

    什么是方法

    方法就是可以对对象做的操作,它们是一些代码块,可以调用这些代码块来完成某个工作。听起来很熟悉?没错,方法就是包含在对象中的函数。

    函数能做到的,方法都可以做到,包括传递参数和返回值。

    对象 = 属性+ 方法

    所以利用对象,可以把一个东西的属性和方法(你知道的事情和你可以做的事情)收集在一起。属性是信息,方法是动作。

    这个点是什么

    在前面的球例子中,你可能已经注意到对象名与属性或方法名之间的点。这是Python使用对象属性和方法的一种记法:object.attribute或object.method()。就这么简单。这称为点记法,很多编程语言中都使用了这种记法。(这个点类似“我的电脑、你的手机”里的那个“的”)

    创建对象

    Python中创建对象包括两步。

    第一步是定义对象看上去什么样,会做什么,也就是它的属性和方法。但是创建这个描述并不会真正创建一个对象。这有点像一个房子的蓝图。蓝图可以告诉你房子看上去怎么样,但是蓝图本身并不是一个房子。你不可能住在一个蓝图里。只能用它来建造真正的房子。实际上,可以使用蓝图盖很多的房子。(在Python中,对象的描述或蓝图称为一个类(class)。

    第二步是使用类来建立一个真正的对象。这个对象称为这个类的一个实例(instance)。

    下面来看一个建立类和实例的例子。代码清单1显示了一个简单的Ball类的类定义:

    image_thumb[1]

    代码清单1是一个球的类定义,其中只有一个方法bounce()。不过,属性呢?嗯,属性并不属于类,它们属于各个实例。因为每个实例可以有不同的属性。

    创建一个对象实例

    前面提到过,类定义并不是一个对象。这只是蓝图。现在来盖真正的房子。

    如果想创建Ball的一个实例,可以这样做:

    myBall = Ball()

    这个球还没有任何属性,所以下面给它提供一些属性:

    myBall.direction = "down"

    myBall.color = "green"

    myBall.size = "small"

    这是为对象定义属性的一种方法。下一节还会学习另一种方法。

    现在来试试它的方法。我们要这样使用bounce()方法:

    myBall.bounce()

    下面把这些都放在一个程序里,增加一些print语句来看发生了什么。程序见代码清单2:

    image_thumb[3]

    运行这个程序,可以看到下面的结果:

    image_thumb[5]

    注意,调用bounce()方法会把球的方向(direction)从下(down)改为上(up),这正是bounce()方法中的代码所要做的。

    初始化对象

    创建球对象时,并没有在size、color或direction中填入任何内容。必须在创建对象之后填充这些内容。不过有一种方法可以在创建对象时设置属性。这称为初始化对象。

    术语箱

    初始化(Initializing)表示开始时做好准备。在软件中对某个东西初始化时,就是把它设置成一种我们希望的状态或条件,以备使用。

    创建类定义时,可以定义一个特定的方法,名为__init__(),只要创建这个类的一个新实例,就会运行这个方法。可以向__init__()方法传递参数,这样创建实例时就会把属性设置为你希望的值。代码清单3显示了这是如何实现的。

    image_thumb[9]

    如果这个程序,得到的输出应该与代码清单2的相同。区别在于,代码清单14-3使用了__init__()方法来设置属性

    “魔法”方法: __str__()

    Python中的对象有一些“魔法”方法,当然它们并不是真的有魔法!这些只是在你创建类时Python自动包含的一些方法。Python程序员通常把它们叫做特殊方法(special method)。

    image

    我们已经知道,__init__()方法会在对象创建时完成初始化。每个对象都内置有一个__init__()方法。如果你在类定义中没有加入自己的__init__()方法,就会有这样一个内置方法接管,它的工作就是创建对象。

    另一个特殊方法是__str__(),它会告诉Python打印(print)一个对象时具体显示什么内容。Python会默认以下内容。

      • 实例在哪里定义(Carter的例子中,就是在__main__中,这是程序的主部分)。
      • 类名(Ball)。
      • 存储实例的内存位置(0x00BB83A0部分)。

    不过,如果你希望print为对象显示其他的内容,可以定义自己的__str__(),这会覆内置的__str__()方法。代码清单4举了个例子

    image

    什么是self

    你可能已经注意到,在类属性和方法定义中多处出现了“self”,比如:

    def bounce(self):

    self是什么意思?嗯,我们说过,可以使用蓝图盖很多个房子,还记得吧?使用一个类也可以创建多个对象实例,例如:

    cartersBall = Ball("red", "small", "down")

    warrensBall = Ball("green", "medium", "up")

    调用其中一个实例的方法时,像这样:

    warrensBall.bounce()

    方法必须知道是哪个实例调用了它。是cartersBall需要反弹吗?还是warrensBall?self参数会告诉方法哪个对象调用它。这称为实例引用(instance reference)。

    不过先等等!调用方法时,warrensBall.bounce()的括号里没有参数,但是方法里却有一个self参数。既然我们并没有传入任何东西,这个self参数从哪里来的?这是Python处理对象的另外一个“魔法”。调用一个类方法时,究竟是哪个实例调用了这个方法?这个信息(也就是实例引用)会自动传递给方法。

    这就像写成:

    Ball.bounce(warrensBall)

    在这种情况下,我们告诉了bounce()方法哪个球要反弹。实际上,这个代. 码也能正常工作,因为写成warrensBall.bounce()时,Python在后台确实也是这么做的。

    顺便说一句,self这个名字在Python中没有任何特殊的含义。只不过所有人都使用这个实例引用名。这也是让代码更易读的一个约定。也可以把这个实例变量命名为你想要的任何名字,不过强烈建议你遵循这个约定,因为使用self能减少混乱。

    之前我们建立过一个热狗程序。现在作为使用对象的例子,我们来为热狗建立一个类。

    一个示例类—— HotDog

    在这个例子中,我们假设热狗总包括一个小面包。(否则可真是一团糟。)下面为热狗指定一些属性和方法。

    下面是热狗的属性。

      • cooked_level:这是一个数字,通过这个属性我们可以知道热狗烤了多长时间。0–3表示还是生的,超过3表示半生不熟,超过5表示已经烤好,超过8表示已经烤成木炭了!我们的热狗开始时是生的。
      • cooked_string:这是一个字符串,描述热狗的生熟程度。
      • condiments:这是热狗上的配料列表,比如番茄酱、芥末酱等。

    下面是热狗的方法。

      • cook():把热狗烤一段时间。这会让热狗越来越熟。
      • add_condiment():给热狗加一些配料。
      • __init__():创建实例并设置默认属性。
      • __str__():让print的结果看起来更好一些。

    首先,需要定义类。先定义__init__()方法,它会为热狗设置默认属性:

    class HotDog:

    def __init__(self):

    self.cooked_level = 0

    self.cooked_string = "Raw"

    self.condiments = []

    先从一个没有加任何配料的生热狗开始。

    现在,来建立一个方法烤热狗:

    def cook(self, time):

    self.cooked_level = self.cooked_level + time

    if self.cooked_level > 8:

    self.cooked_string = "Charcoal"

    elif self.cooked_level > 5:

    self.cooked_string = "Well-done"

    elif self.cooked_level > 3:

    self.cooked_string = "Medium"

    else:

    self.cooked_string = "Raw"

    继续下面的工作之前,先对这一部分做个测试。首先,需要创建热狗的一个实例,还要检查它的属性。

    myDog = HotDog()

    print myDog.cooked_level

    print myDog.cooked_string

    print myDog.condiments

    下面把这些内容都放在一个程序中,运行这个程序。代码清单5显示了(到目前为止)完整的程序。

    # 代码清单 5 热狗程序的开始部分

    class HotDog:

    def __init__(self):

    self.cooked_level = 0

    self.cooked_string = "Raw"

    self.condiments = []

    def cook(self, time):

    self.cooked_level = self.cooked_level + time

    if self.cooked_level > 8:

    self.cooked_string = "Charcoal"

    elif self.cooked_level > 5:

    self.cooked_string = "Well-done"

    elif self.cooked_level > 3:

    self.cooked_string = "Medium"

    else:

    self.cooked_string = "Raw"

    myDog = HotDog()

    print myDog.cooked_level

    print myDog.cooked_string

    print myDog.condiments

    提示:Python中的另一个约定是类名总是以大写字母开头。目前为止,我们已经见到BallHotDog,所以说我们一直都在遵循这个约定。

    现在,运行代码清单14-5中的代码,看看会得到什么。结果应该像这样:

    >>>

    0

    Raw

    []

    >>> 

    可以看到,属性分别是cooked_level = 0,cooked_string = "Raw",另外condiments为空。

    现在来测试cook()方法。把下面的代码行增加到代码清单5中:

    print "Now I'm going to cook the hot dog"

    myDog.cook(4)

    print myDog.cooked_level

    print myDog.cooked_string

    再运行这个程序,现在输出会变成:

    >>>

    0

    Raw

    []

    Now I'm going to cook the hot dog

    4

    Medium

    >>> 

    看来我们的cook()方法能正常工作。cooked_level从0变成4,而且字符串也得到更新(从Raw变成Medium)。

    下面来增加一些配料。这需要一个新的方法。另外还可以自己增加__str__()函数,让打印对象更为容易。按代码清单6编辑程序。

    image

    image

    这个代码清单有点儿长,但我还是建议你自己键入这些代码,而且你已经有了之前代码清单5中的部分代码

    运行这个程序,看看能得到什么。结果应该如下:

    >>> ================================ RESTART ================================

    >>> 

    Raw hot dog.

    Cooking hot dog for 4 minutes...

    Medium hot dog.

    Cooking hot dog for 3 more minutes...

    Well-done hot dog.

    What happens if I cook it for 10 more minutes?

    Charcoal hot dog.

    Now, I'm going to add some stuff on my hot dog

    Charcoal hot dog with ketchup, mustard.

    >>> 

    程序的第一部分创建了类。第二部分测试了烤这个虚拟热狗和添加配料的方法。不过从最后几行代码来看,我认为烤得太过了。这太浪费番茄酱和芥末酱了!

  • 相关阅读:
    angularjs的$on、$emit、$broadcast
    angularjs中的路由介绍详解 ui-route(转)
    ionic入门教程-ionic路由详解(state、route、resolve)(转)
    Cocos Creator 加载使用protobuf第三方库,因为加载顺序报错
    Cocos Creator 计时器错误 cc.Scheduler: Illegal target which doesn't have uuid or instanceId.
    Cocos Creator 构造函数传参警告 Can not instantiate CCClass 'Test' with arguments.
    Cocos Creator 对象池NodePool
    Cocos Creator 坐标系 (convertToWorldSpaceAR、convertToNodeSpaceAR)
    Cocos Creator 常驻节点addPersistRootNode
    Cocos Creator 配合Tiled地图的使用
  • 原文地址:https://www.cnblogs.com/jlxuqiang/p/4105868.html
Copyright © 2020-2023  润新知