天天看点

Day08 - 面向对象编程基础

日期:2021年1月25日

今天是学习Python的第八天,到面向对象了,相较于昨天,今天的内容合理多了,学起来也快一些。

学习用的教材是GitHub上骆昊编写的《Python - 100天从新手到大师》

所有编写的源代码均放在GitHub上:https://github.com/svip886/Python_learning

一、类和对象

简单的说,类是对象的蓝图和模板,而对象是类的实例。类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。

二、类的定义和对象的使用

Python和C++一样,使用关键字

class

来定义类,下面是创建类的示例

定义一个矩形Rect类,并写出计算周长和面积的成员函数:

class Rect:
    # __init__是一个特殊方法用于在创建对象时进行初始化,就像C++中的构造函数
    def __init__(self,l,w): # 为Rect对象绑定长度l,宽度w
        self.l=l
        self.w=w

    def circumference(self):
        print('矩形周长为',2*self.l*self.w)

    def area(self):
        print('矩形面积为',self.l*self.w)

def main():
    # 创建Rect对象并赋予长和宽
    s=Rect(3,2)
    # 调用计算长度和宽度的成员函数
    s.circumference()
    s.area()

if __name__=='__main__':
    main()
           

二、访问可见性问题

Python和C++不同,对象的方法通常都是公开的(pubilc),如果希望属性是私有的(private),可以在属性命名是用两个下划线

"__"

作为开头,使其隐藏,但仍可以通过

_类名__成员

来访问它,等于加了一层保护。

同样的例子,稍作修改

class Rect:

    def __init__(self,l,w):
        self.l=l # 将属性设为私有
        self.__w=w

    def circumference(self):
        print('矩形周长为',2*self.l*self.__w)

    def __area(self):
        print('矩形面积为',self.l*self.__w)

def main():
    s=Rect(3,2)
    s.circumference() # 矩形周长为12
    s.__area() # AttributeError: 'Rect' object has no attribute '__area'
    s._Rect__area() # 矩形面积为6
    print(s.l) # 3
    print(s.__w) # AttributeError: 'Rect' object has no attribute '__w'
    print(s._Rect__w) # 2

if __name__=='__main__':
    main()
           

💡 实际开发中,不建议将属性设为私有,这会导致子类无法访问。所以一个好的习惯是,让属性名以单下划线开头来表示属性是受保护的,更多的是像一种暗喻,提醒自己本类外使用需要慎重。

三、练习

  1. 定义一个类描述数字时钟
    from time import sleep
    from os import system
    class Clock:
        def __init__(self,hour=0,minute=0,second=0):
            self._hour=hour
            self._minute=minute
            self._second=second
    
        def run(self):
            self._second+=1
            if self._second==60:
                self._second=0
                self._minute+=1
                if self._minute==60:
                    self._minute=0
                    self._hour+=1
                    if self._hour==24:
                        self._hour=0
    
        def output(self):
            while 1:
                self.run()
                system('cls')
                print('当前时间:%02d:%02d:%02d' % (self._hour,self._minute,self._second))
                sleep(1)
    
    def main():
        s=Clock(13,12,55)
        s.output()
    
    if __name__=='__main__':
        main()
               
    💡 结合了之前的跑马灯练习学来的

    os.system()

    函数,实现了命令行的时间刷新。
  2. 定义一个类描述平面上的点并提供移动点和计算到另一个点距离的方法
    class Point:
        def __init__(self,x=0,y=0):
            self._x=x
            self._y=y
    
        def output(self):
            print('当前点的坐标为(%d,%d)' % (self._x,self._y))
    
        def move(self):
            self._x=int(input('x='))
            self._y=int(input('y='))
    
        def distance(self,a):
            d=((self._y-a._y)**2+(self._x-a._x)**2)**0.5
            print('两点之间的距离为:%.2f' % (d))
    
    def main():
        p1=Point(2,4)
        p2=Point(3,3)
        p1.output()
        p2.output()
        p1.move()
        p1.output()
        p1.distance(p2)
    
    if __name__=='__main__':
        main()