zoukankan      html  css  js  c++  java
  • python面向对象基础

    概述

    • 面向过程:根据业务逻辑从上到下写垒代码
    • 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
    • 面向对象:对函数进行分类和封装,让开发“更快更好更强...

    创建类和对象

    • class是关键字,表示类
    • 类名后加括号表示创建对象

    ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
       类中定义的函数叫做 “方法”

    面向对象三大特性

      面向对象的三大特性是指:封装、继承和多态。

    一、封装

     个人编写的小游戏(战斗环节)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import time
    import random
    class wu_lin:
        def __init__(self,name,wugong,life):
            self.name=name
            self.wugong=wugong
            self.life=life
        def pugong(self):
            self.life-=1
        def xiulian(self):
            self.life+=2
    
    class wu_dang(wu_lin):
        def neigong(self):
            self.life-=3
            time.sleep(0.2)
    class shao_lin(wu_lin):
        def neigong(self):
            self.life-=3
            time.sleep(0.2)
    
    zhangsanfeng=wu_dang('张三丰','太极拳',20)
    zhangwuji=wu_dang('张无忌','乾坤大挪移',20)
    yideng=shao_lin('一灯大师','一阳指',20)
    fangzheng=shao_lin('方正大师','神照经',20)
    
    
    while True:
        a=random.randint(1,8) #a=1张三丰攻击(一灯大师掉血),a=2一灯大师攻击(张三丰掉血)
        b=random.randint(1,9) #b=1普通攻击,b=2内功或外功攻击
        if a==1 or a==2:
            if b==1 or b==2 or b==3 or b==4:
                yideng.pugong()
                print('%s受到%s的普通攻击,剩余血量为%s' %(yideng.name,zhangsanfeng.name,yideng.life))
            else:
                yideng.neigong()
                print('%s使用  %s  攻击了%s,%s剩余血量为%s' %(zhangsanfeng.name,zhangsanfeng.wugong,
                                                yideng.name,yideng.name,yideng.life))
        elif a==3 or a==4:
            if b==1 or b==2 or b==3 or b==4:
                zhangsanfeng.pugong()
                print('%s受到%s的普通攻击,剩余血量为%s' %(zhangsanfeng.name,yideng.name,zhangsanfeng.life))
            else:
                zhangsanfeng.neigong()
                print('%s使用  %s  攻击了%s,%s剩余血量为%s' %(yideng.name,yideng.wugong,zhangsanfeng.name,zhangsanfeng.name,zhangsanfeng.life))
        elif a==5 or a==6:
            if b==1 or b==2 or b==3 or b==4:
                zhangwuji.pugong()
                print('%s受到%s的普通攻击,剩余血量为%s' %(zhangwuji.name,fangzheng.name,zhangwuji.life))
            else:
                zhangwuji.neigong()
                print('%s使用  %s  攻击了%s,%s剩余血量为%s' %(fangzheng.name,fangzheng.wugong,
                                                zhangwuji.name,zhangwuji.name,zhangwuji.life))
        elif a==7 or a==8:
            if b==1 or b==2 or b==3 or b==4:
                fangzheng.pugong()
                print('%s受到%s的普通攻击,剩余血量为%s' %(zhangsanfeng.name,yideng.name,zhangsanfeng.life))
            else:
                fangzheng.neigong()
                print('%s使用  %s  攻击了%s,%s剩余血量为%s' %(zhangwuji.name,zhangwuji.wugong,fangzheng.name,fangzheng.name,fangzheng.life))
        if yideng.life<=0:
            print('%s已经阵亡' %yideng.name)
            print('%s夺取武林盟主之位' %zhangsanfeng.name)
            break
        if zhangsanfeng.life<=0:
            print('%s已经阵亡' %zhangsanfeng.name)
            print('%s夺取武林盟主之位' %yideng.name)
            break
        if fangzheng.life<=0:
            print('%s已经阵亡' %fangzheng.name)
            print('%s夺取武林盟主之位' %zhangsanfeng.name)
            break
        if zhangwuji.life<=0:
            print('%s已经阵亡' %zhangwuji.name)
            print('%s夺取武林盟主之位' %yideng.name)
            break
    

    二、继承

    面向对象中的继承跟生活中的继承一个道理,即:子可以继承父的内容。

         python中继承跟其他语言不同的地方在于:Java或C++中面向对象的继承只能继承一个,即只能继承父类;

    而python中面向对象的继承则能继承多个,即可以继承父亲的又可以继承叔叔的,寻找方法的顺序则是从左到右进行溯源。

    class Animals:
        def chi(self):
            print(self.name+'吃吃吃')
        def he(self):
            print(self.name+'喝喝喝')
    class Dog(Animals):#类名后面有括号就是继承,没括号就是基类
        def __init__(self,name):
            self.name=name
        def jiao(self):
            print(self.name+'汪汪汪')
    obj1=Dog('xx')
    obj1.jiao()
    obj1.chi()
    obj1.he()
    

    注意:多继承时,python2.7未继承object时(经典类),深度优先,即一条道走到黑

       python3.5顶部留到最后  

    多继承的优先级关系:当继承多个类发生冲突时,优先级是:先自己,然后先左再右

    • 当类是经典类时,多继承情况下,会按照深度优先方式查找
    • 当类是新式类时,多继承情况下,会按照广度优先方式查找

    经典类的格式:class Classics:

    #经典类多继承的栗子:
    class D:                  #经典类
        def bar1(self):
            print("D.bar1")
    
    class C(D):
        def bar1(self):
            print("C.bar1")
    
    class B(D):
        # def bar1(self):
        #     print "B.bar1"
        pass                  #pass 代表什么也不做
    
    class A(B,C):
        # def bar1(self):
        #     print("A.bar1")
        pass                  #pass 代表什么也不做
    
    op = A()                  #实例化对象op
    op.bar1()
    
    #######执行结果如下#######
    D.bar1
    

      原理:

    当我们实例化op,并且调用bar1方法时,由于在类中有多个bar1方法,因此对于经典类,它自己有一个查找顺序,A ---> B --> D --> C
    具体描述:
    首先找A,如果A中没有,则找B,如果B中没有,再找D,如果D中也没有,最后找C,都没有找到,则报错;这种访问方式叫做深度优先
    
    对于上面这个例子,由于找A 和 B 时都没有找到,则找到了D,因此打印了D.bar1,
    
    分析结果——深度优先
    

      

    新式类的格式:class New(object):

        对于新式类,要在类名后的括号中写上object,object 也是一个类,class New(object),相当于继承了object 类,

    则这个类称为新式类,新式类是我们今后推荐的写法。

    #新式类多继承的栗子:
    class Tina(object):    #新式类
        def f1(self):
            print('Tina')
    class A(Tina):
        def f(self):
            print('A')
    class B(Tina):
        def f(self):
            print('B')
    class C(A):
        def f(self):
            print('C')
    class D(B):
        def f(self):
            print('D')
    class E(C,D):
        def f(self):
            print('E')
    obj=E()
    obj.f1()
    
    ###########执行结果如下#########
    Tina
    

      原理:

    # 首先去C类中查找,如果C类中没有,则继续去A类中找,如果A类中没有,则继续去D类中找,如果D类中么有,则继续去B类中找,如果B中没有,去T中去找,还是未找到,则报错
    # 所以,查找顺序:C --> A --> D --> B --> T
    # 在上述查找方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    

      继承案例:(super 推荐 ,父类.__Init(self) 不推荐)

    class Animal:
        def __init__(self):
            print("a的构造方法")
            self.a = "动物"
     
     
    class Cat(Animal):
        def __init__(self):
            print("b的构造方法")
            self.b = "mao"
            super(Cat, self).__init__() # 推荐这种 继承父类的init所有属性 记住self的位置。由super解决
            # Animal.__init__(self)  # 这种方法不推荐,容易混乱
     
     
     
    c1 = Cat()
    print(c1.__dict__)
    

    三、多态

    多态的概念是应用于Java和C#这一类强类型语言中,他们在传参数时需要指定参数类型,python本身就支持传各种类型的参数,本身就是多态。

    问答专区

    问题一:什么样的代码才是面向对象?

    答:从简单来说,如果程序中的所有功能都是用 类 和 对象 来实现,那么就是面向对象编程了。

    问题二:函数式编程 和 面向对象 如何选择?分别在什么情况下使用?

    答:须知:对于 C# 和 Java 程序员来说不存在这个问题,因为该两门语言只支持面向对象编程(不支持函数式编程)。而对于 Python 和 PHP 等语言却同时支持两种编程方式,且函数式编程能完成的操作,面向对象都可以实现;而面向对象的能完成的操作,函数式编程不行(函数式编程无法实现面向对象的封装功能)。

    所以,一般在Python开发中,全部使用面向对象 或 面向对象和函数式混合使用

    面向对象的应用场景:

    1.多函数需使用共同的值,如:数据库的增、删、改、查操作都需要连接数据库字符串、主机名、用户名和密码

    class SqlHelper:
    
        def __init__(self, host, user, pwd):
    
            self.host = host
            self.user = user
            self.pwd = pwd
    
        def 增(self):
            # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
            # do something
            # 关闭数据库连接
    
        def 删(self):
            # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
            # do something
            # 关闭数据库连接
    
        def 改(self):
            # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
            # do something
            # 关闭数据库连接
    
        def 查(self):
        # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
            # do something
            # 关闭数据库连接# do something
    
    Demo
    

      2.需要创建多个事物,每个事物属性个数相同,但是值的需求
    如:张三、李四、杨五,他们都有姓名、年龄、血型,但其都是不相同。即:属性个数相同,但值不相同

    class Person:
    
        def __init__(self, name ,age ,blood_type):
    
            self.name = name
            self.age = age
            self.blood_type = blood_type
    
    
        def detail(self):
            temp = "i am %s, age %s , blood type %s " % (self.name, self.age, self.blood_type)
            print temp
    
    zhangsan = Person('张三', 18, 'A')
    lisi = Person('李四', 73, 'AB')
    yangwu = Person('杨五', 84, 'A')
    
    Demo
    

      问题三:类和对象在内存中是如何保存?

    答:类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图

    如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值指向当前对象的类。

    当通过 obj1 执行 【方法一】 时,过程如下:

    1. 根据当前对象中的 类对象指针 找到类中的方法
    2. 将对象 obj1 当作参数传给 方法的第一个参数 self 
  • 相关阅读:
    激活第一个CPU
    每CPU变量
    在 Vue中使用layui日历控件,标注重要日子
    手机号,银行卡断开方式
    下载文件流
    使用class关键字创建类组件、props参数
    class继承关键字extends和super
    用于判断文件是已什么结尾的
    flex一些属性
    类组件
  • 原文地址:https://www.cnblogs.com/wanghzh/p/5555183.html
Copyright © 2011-2022 走看看