• 零基础学习python_类和对象(36-40课)


      今天我们开始学习面向对象的知识咯,之前我对面向对象也学的懵懵的,因为感觉知道好像又不是特别清楚,接下来我们一起来学习类和对象吧。零基础的课程我都是看小甲鱼的视频学的,没基础的可以去这个网址下载视频学习:http://blog.fishc.com/category/python

      好了,我们开始进行学习吧,我们先来思考下,对象是什么?抛开程序代码,我们想一下如果人是一个对象,那么这个对象有什么呢?

      你是不是会说这个人长得怎么样,眼睛咋样,身高多少,对这个人的外貌特征进行描述,那么这个人能干什么呢?是不是能吃饭、走路、说话等。

      那么你想下对于人这个对象来说是不是有特征和行为这两大特性呢?那么对于程序来说对象也是如此,对象 = 属性 + 方法

    下面就是第一个实例,有属性和方法,注意:类的名称第一个字母为大写,函数为小写(约定俗成的习惯吧!)

    #coding = utf-8
    class Person:  #无括号是旧的书写方式,有括号是新的书写方式
        '''第一个简单类实例_人'''
        height = 180    #属性,是不是很像变量
        weight = 70
    
    #下面是方法 def run(self):    #是不是就是一个个函数呢? print('我跑啊跑啊跑。。。') def sing(self): print('我唱歌唱啊唱啊。。。')

     下面是类的实例化,很简单的,直接赋值给一个变量,就可以通过变量来调用内的不同方法了

    面向对象的特征:

    • 封装:对外部隐藏对象的工作细节
    • 继承:子类自动共享父类之间的数据和方法的机制
    • 多态:可以对不同类的对象调用相同的方法,产生不同的结果

     你可能发现上面定义类的时候函数的括号里面都有self这个东东,那这个是啥呢?

    举个例子大家看下:

    class Test():
        def __init__(self,name):   #构造函数
            self.name = name   #name传入后赋值
        
        def run(self):
            print('%s 在跑。。。。'%self.name)  #对name进行调用,记得写self不然不知道你要调用的name在哪里

    调用结果如下:

    对于同一个类,那么我在调用的时候怎么区别是谁调的呢?self就是帮你解决这件事情的,self就是指的自己,也就是说是谁实例化的呢?a=Test就等同于Test(a),所以这个是不可缺少的,当前你可以不用self,可以用任意英文代替,不过大家都统一的事情你还是默认这样写吧。

    类里面也有公有和私有之分,像我们之前看到的变量都是公有的,私有变量的话需要在变量前加入双下划线“__”,这样外面就不能调用了,当然实际上也是可以的,举个例子看看吧。

    其实__变量虽然访问不到,但是也可以通过“_类__变量”进行访问

     下面给个题目大家做一下,我刚开始没做出来,感觉有点难,后面看了下答案觉得还好,大家可以想一下:

    答案如下:

    import random as r
    
    legal_x = [0,10]
    legal_y = [0,10]
    
    class Turtle:
        def __init__(self):
            #初始体力
            self.power = 100
    
            #初始位置随机
            self.x = r.randint(legal_x[0],legal_x[1])
            self.y = r.randint(legal_y[0],legal_y[1])
    
        def move(self):
            #随机计算方向并移动到新的位置(x,y)
            new_x = self.x + r.choice([1,2,-1,-2])
            new_y = self.y + r.choice([1,2,-1,-2])
    
            #检查移动后是否超出场景x轴边界
            if new_x < legal_x[0]:
                self.x = legal_x[0] - (new_x - legal_x[0])
            elif new_x > legal_x[1]:
                self.x = legal_x[1] - (new_x - legal_x[1])
            else:
                self.x = new_x
    
            #检查移动后是否超出场景y轴边界
            if new_y < legal_y[0]:
                self.y = legal_y[0] - (new_y - legal_y[0])
            elif new_y > legal_y[1]:
                self.y = legal_y[1] - (new_y - legal_y[1])
            else:
                self.y = new_y
    
            #体力消耗
            self.power -= 1
    
            #返回移动后的新位置
            return(self.x, self.y)
    
        def eat(self):
            self.power += 20
            if self.power > 100:
                self.power = 100
    
    class Fish:
        def __init__(self):
            #初始位置随机
            self.x = r.randint(legal_x[0],legal_x[1])
            self.y = r.randint(legal_y[0],legal_y[1])
    
        def move(self):
            #随机计算方向并移动到新的位置(x,y)
            new_x = self.x + r.choice([1,-1])
            new_y = self.y + r.choice([1,-1])
    
            #检查移动后是否超出场景x轴边界
            if new_x < legal_x[0]:
                self.x = legal_x[0] - (new_x - legal_x[0])
            elif new_x > legal_x[1]:
                self.x = legal_x[1] - (new_x - legal_x[1])
            else:
                self.x = new_x
    
            #检查移动后是否超出场景y轴边界
            if new_y < legal_y[0]:
                self.y = legal_y[0] - (new_y - legal_y[0])
            elif new_y > legal_y[1]:
                self.y = legal_y[1] - (new_y - legal_y[1])
            else:
                self.y = new_y
    
            #返回移动后的新位置
            return(self.x, self.y)
    
    
    turtle = Turtle()
    
    fish = []
    
    for i in range(10):
        new_fish = Fish()
        fish.append(new_fish)
    
    
    while True:
        if not len(fish):
            print("鱼儿都吃完了,游戏结束!")
            break
        if not turtle.power:
            print("乌龟体力耗尽,挂掉了!")
            break
    
        pos = turtle.move()
    
    
        for each_fish in fish[:]:
            if each_fish.move() == pos:
                #鱼儿被吃掉了
                fish.remove(each_fish)
                turtle.eat()       

    写完这个例子相信你对类其实了解一些了,接着我们来学习下类的继承,听名字好像又是什么高大上的东西,不怕其实是个很简单的东东。

    举个简单的例子,假设你写了一个黄种人的类,但是又要写黑人、白人的类呢?全部重新写方法吗?直接看代码,来:

    class Yello_person():
    
        def __init__(self):
            self.skin = 'yellow'
            #self.name = 'liu'
    
        def eat(self):
            self.food = 'rice'
            print("%s种人在吃%s"%(self.skin,self.food))
    
    class Black_person(Yello_person):  #继承Yello_person类的所有
    def __init__(self):       #重写__init__这个构造函数,因此
      self.skin
    = 'black'

    大家看这就是继承,可以继承父类、基类、超类,继承之后可以拥有父类的所有属性和方法,如果重写了就会读取自己写的属性和方法,那么有个问题来了,如果我又想继承部分属性又想自己定义部分属性呢?

    那么接着看刚刚那么例子,用super()继承即可:

    class Yello_person():
    
        def __init__(self):
            self.skin = 'yellow'
            self.name = 'liu'
    
        def eat(self):
            self.food = 'rice'
            print("叫%s的%s种人在吃%s"%(self.name,self.skin,self.food))
    
    class Black_person(Yello_person):
    
        def __init__(self):
            super().__init__()      #继承父类的__init__()下的属性
            self.skin = 'black'

    或者用下面这种方法,父类.__init__(self):

    class Yello_person():
    
        def __init__(self):
            self.skin = 'yellow'
            self.name = 'liu'
    
        def eat(self):
            self.food = 'rice'
            print("叫%s的%s种人在吃%s"%(self.name,self.skin,self.food))
    
    class Black_person(Yello_person):
    
        def __init__(self):
            Yello_person.__init__(self)          #继承父类的__init__属性
            self.skin = 'black'

    这两个结果都是一样的,都可以继承,建议写super(),因为修改的话只要修改一个地方的类就好了,第二种方法要修改很多处。

    接下来说下多重继承,其实就是class Person(class1,class2,class3),逗号隔开即可,看个实例:

    class Yello_person():
    
        def __init__(self):
            self.skin = 'yellow'
    
        def eat(self):
            self.food = 'rice'
            print("%s种人在吃%s"%(self.skin,self.food))
    
    class Black_person():
    
        def __init__(self):
            self.skin = 'black'
    
    
    class White_person(Black_person,Yello_person):
        pass

    注意,如果继承时Yello_person写在前面则会打印这个,所以多重继承时,如果出现重复的,默认是选择第一个类的属性或方法。

    接着看下下面的题目:

    1、定义一个点(Point)类和直线(Line)类,使用getLen方法获得直线的长度。

    代码如下:

    import math
    class Point():
    
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
    
        def getX(self):
            return self.x
    
        def getY(self):
            return self.y
    
    class Line():
        
        def __init__(self,p1,p2):
            self.x = p1.getX() - p2.getX()
            self.y = p1.getY() - p2.getY()
            self.len = math.sqrt(self.x*self.x + self.y*self.y)               #获取两点之间的数学公式
    
    
        def getLen(self):
            return self.len
        

       之前说了类的继承和多重继承,那么如果说我们要定义一个房子,里面有人和家具,那么显然用继承是不合理的,因为这个类就是四不像了,那么这个时候该怎么办呢?——组合,没错就是类的组合,举个例子大家看下就好了;

    class Person:
    
        def __init__(self,num):
            self.num = num
    
    class Jiaju:
    
        def __init__(self,num):
            self.num = num
    
    
    class room:
    
        def __init__(self,pnum,jnum):
            self.pnum = Person(pnum)             #实例化人这个类然后赋值给一个变量
            self.jnum = Jiaju(jnum)        #实例化家具这个类然后赋值给一个变量
    def retrunnum(self): print("房子里面总共有%d人和%d家具!"%(self.pnum.num, self.jnum.num))

    运行结果可以看下:

    组合就是将类的实例化放在新的类中,这样就完成了组合 

    类、类对象和实例对象

        

    这个图是三个的关系图,简单说一下,刚开始看我觉得类定义和类对象分不清,实际上当类定义执行完后就变成了类对象,实例对象就是对类对象的实例化而已。

    注意:类中的方法名与属性名重名时,类将被属性覆盖,来看个实例:

    >>> class Person:
        def name(self):
            print('king')
    
            
    >>> p1 = Person()
    >>> p1.name()
    king
    >>> p1.name = 1
    >>> p1.name()
    Traceback (most recent call last):
      File "<pyshell#7>", line 1, in <module>
        p1.name()
    TypeError: 'int' object is not callable

    绑定:python严格要求方法需要有实例才能被调用,这种限制其实就是python所谓的绑定概念。

      1、issubclass(class, classinfo)

        a、一个类被认为是其自身的子类

        b、classinfo可以是类对象组成的元组,只要class是其中任何一个子类,则返回True

      2、isinstance(object,classinfo)

        a、如果第一个参数不是对象,则永远返回False

        b、如果第二个参数不是类或者由类对象组成的元组,会抛出一个TypeError异常。

      3、hasattr(object,name):测试一个对象是否有指定的属性

      4、getattr(object, name[, default]):返回对象指定的属性值

      5、setattr(object,name,value):设置指定属性的值

      6、delattr(object,name):删除对象中指定的属性,如果属性不存在抛出异常。

    还有一个属性函数,property

    下表列出了可以在自己的类中覆盖的一些通用方法 

    给个题目大家看下:

    请在类中定义一个变量,用于跟踪该类有多少个实例被创建(实例化一个对象时,变量+1,销毁一个对象时,变量自动-1)

    代码如下;

    class A:
        
        count = 0
    
        def __init__(self):
            A.count += 1
    
        def __del__(self):
            A.count -= 1

  • 相关阅读:
    取最小未用的账号
    Oracle 同义词
    RMAN备份报 RMAN-06059 错误
    Oracle11g memory_target
    基础记录
    uboot启动流程
    android有关生命周期探讨
    can协议
    java虚拟机
    内存管理机制
  • 原文地址:https://www.cnblogs.com/leixiaobai/p/7827929.html
Copyright © 2020-2023  润新知