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

    >>> 

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

  • 相关阅读:
    redis配置文件redis.conf总结
    react井字棋小游戏实现及优化
    springboot 如何在请求进入controller之前改变body中的值
    记录一个Springboot启动的问题->sprinboot正常启动但是tomcat却没有启动
    websocket-基于springboot的简单实现
    JVM-垃圾回收
    gRPC-Java实践
    Protocol Buffers—-java
    串口通信学习-基础
    Modbus通信协议学习
  • 原文地址:https://www.cnblogs.com/jlxuqiang/p/4105868.html
Copyright © 2020-2023  润新知