• Python全栈开发之6、面向对象


    一、创建类和对象

    面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用

    类是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)

    对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数

    def Dog(name,type):
    
        def call(dog):
    
            print("这是一条%s,名字叫%s"%(dog['type'],dog['name']))
    
        def eat(dog):
    
            print("%s正在啃骨头"%dog['type'])
    
        def init(name,type):
    
            dog_dcit={'name':name,'type':type,'call':call,'eat':eat}
    
            return dog_dcit
    
        res=init(name,type)
    
    
        return res
    
    
    d1=Dog('小狗',"中华田园犬")
    
    d1['call'](d1)
    d1['eat'](d1)
    面向对象设计

    类的成员可以分为三大类:字段(类变量)、方法(动态属性)和属性(静态属性)

    1、类的语法

    在python3.0 中有两种写法,一种是经典类还有一种是新式类

    经典类和新式类的区别:继承方法上的区别,分为广度优先和深度优先两种继承策略

    class Dog:                           #经典类,类名后不加括号
     
        def __init__(self,name):   #构造函数
          
              self.name=name
            
    
        def bulk(self):
            print('%s,汪汪'%self.name)
    
    
    
    d1 = Dog("小红")   #初始化一个类 构造一个对象   self相当于d1   Dog(d1,"小红")
    d2 = Dog("小明")
    
    d1.bulk()
    d2.bulk()
    经典类
    class Dog(object):                #新式类,类名后加括号(object)
     
        def __init__(self,name):   #构造函数
          
              self.name=name
            
    
        def bulk(self):
            print('%s,汪汪'%self.name)
    
    
    
    d1 = Dog("小红")   #初始化一个类 构造一个对象   self相当于d1  Dog(d1,"小红")
    d2 = Dog("小明")
    
    d1.bulk()
    新式类

    2、类变量、方法和属性

    类变量:在类中定义的变量class Role(object): #定义类

        
        num=123               #类变量,大家都可以调用
        num_list=[]
        
        def __init__(self, name, role, weapon, life_value=100, money=15000):  #构造函数    在实例化时做一些类的初始化的工作
    
            self.name = name     #self.name 赋给实例   实例变量(静态属性)  作用域就是实例本身
            self.role = role
            self.weapon = weapon
            self.__life_value = life_value   #私有属性前面要加两个下划线__来定义,私有属性只可以在方法里面调用
            self.money = money
    
    
        def __del__(self):  #析构函数    实例或者对象消亡或者程序结束时才调用
                            #在实例释放或销毁的时候自动执行,通常用于做一些收尾工作
                            #如:关闭一些数据库连接,打开的临时文件
            print("%s 彻底死了。。。。"%self.name)
     
           
    
        def shot(self):
            print("shooting...")
    
    
        def got_shot(self):          #定义类的方法(功能)也叫作动态属性
            print("ah...,I got shot...")
    
        def buy_gun(self,gun_name):      
            print("%s just bought %s" %(self.name,gun_name)) #方法里的self  self.name 相当于r1.name 
    
    
        def show_life(self):
    
            print("life %s"%self.__life_value)   #私有属性  只可以在内部方法里调用
    
        def __get_weapon(self):                  #定义私有方法   在定义方法名前加两个下划线,私有方法也是只能在类方法中被调用
            print('私有方法')
    
    Role_dict=Role.__dict__    # 查看类的属性字典
    
    print(Role_dict)  
    #输出:{'__module__': '__main__', 'num': 123, 'num_list': [], '__init__': <function Role.__init__ at 0x10ed6c290>, '__del__': <function Role.__del__ at 0x10ed6c320>, 'shot': <function Role.shot at 0x10ed6c710>, 'got_shot': <function Role.got_shot at 0x10ed6c7a0>, 'buy_gun': <function Role.buy_gun at 0x10ed6c830>, '_Role__get_weapon': <function Role.__get_weapon at 0x10ed6c8c0>, 'show_life': <function Role.show_life at 0x10ed6c950>, '__dict__': <attribute '__dict__' of 'Role' objects>, '__weakref__': <attribute '__weakref__' of 'Role' objects>, '__doc__': None}

    r1 = Role('Alex', 'police', 'AK47') # 生成一个角色 (初始化一个类,造了一个对象) 把一个类变成一个具体对象的过程叫实列化
    # Role(r1,'Alex','police','AK47') r1.name=name 是这样实例的

    #Role(r1,'Alex','police','AK47') self.name 相当于 r1.name

    # print(r1.__dict__) #查看实例的属性字典
    #输出:{'name': 'Alex', 'role': 'police', 'weapon': 'AK47', '_Role__life_value': 100, 'money': 15000}
    r2 = Role('Jack', 'terrorist', 'B22') # 生成一个角色 r1.buy_gun('AK-47') r2.buy_gun('加特林') r1.n=456 print(r1.n) #输出是456 互不影响 r3=Role('lucy','artist','AK47') print(r3.n) #输出是123 在实例r1中值被修改 但是在实例r3中不影响,互相独立 只是类在实例化对象时 都独自开辟了一块内存 Role.n=789 print(r1.n,r3.n) #输出 r1.n是456不是789 因为r1.n已经被实例化过r3.n是789

    3、类属性的增删查改

    class Chinese:
    
        country="China"
    
        def __init__(self,name):
    
            self.name=name
    
        def play_ball(self,ball):
    
            print("%s 正在打 %s"%(self.name))
    
        def sayWord(self,word):
            print("%s 说 %s"%(self.name,word))
    
    
    # 查看类的属性
    print(Chinese.country)
    
    # 修改类的属性
    Chinese.country ="Japan"
    p1=Chinese("allen")
    
    print(Chinese.country,p1.country)
    
    # 删除类的属性
    # del Chinese.country
    # print(Chinese.country)  # 会报错
    
    # 增加类的属性
    Chinese.language = "汉语"
    p2=Chinese("lucy")
    print(Chinese.country,p2.country,p2.language)
    print(Chinese.__dict__)
    
    # 函数属性的增删改查
    
    def learning(self,course):
    
        print("%s is learning %s"%(self.name,course))
    
    Chinese.learn=learning
    
    p3=Chinese("Lily")
    
    p3.learn("france")
    类属性的增删改查
    class Chinese:
    
        country="China"
    
        def __init__(self,name):
    
            self.name=name
    
        def play_ball(self,ball):
    
            print("%s 正在打 %s"%(self.name,ball))
    
        def sayWord(self,word):
            print("%s 说 %s"%(self.name,word))
    
    
    # 查看实例的属性
    p1=Chinese("allen")
    print(p1.name)
    print(p1.play_ball)
    
    # 增加实例的属性
    p1.age = 18
    print(p1.__dict__)
    
    # 修改实例的属性
    p1.age = 19
    
    print(p1.__dict__)
    实例属性的增删改查

    4、类的组合

    class Head:
        pass
    
    class Foot:
        pass
    
    class Body:
        pass
    
    
    class Person:
        def __init__(self,id_num,name):
    
            self.id_num=id_num
            self.name=name
            self.head=Head()  # 实例化一个Head类
            self.body=Body()  # 实例化一个Body类
            self.foot=Foot()  # 实例化一个Foot类
    
    p=Person("123456","allen")
    
    print(p.__dict__)
    组合
    class School:
        def __init__(self,name,address):
    
            self.name=name
            self.address=address
    
        def academy(self):
            print("%s学校的地址是%s"%(self.name,self.address))
    
    class Course:
        def __init__(self,course_name,school):
            self.course_name=course_name
    
            self.school=school
    
    
    s1=School("山东大学","济南")
    s2=School("北京大学","北京")
    s3=School("深圳大学","深圳")
    
    msg="""
    1.山东大学
    2.北京大学
    3.深圳大学
    """
    
    while True:
        print(msg)
        schoolInfo={"1":s1,"2":s2,"3":s3}
        choice=input("请选择学校:")
        courseName=input("请输入课程名:")
        c1=Course(courseName,schoolInfo[choice])
        
        print("课程%s属于%s"%(c1.course_name,c1.school.name))
    示例-选课系统

    二、面向对象三大特性

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

     1、继承

    继承概念的实现方式主要有2类:实现继承、接口继承。

    Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;
    Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法);
    在python2中 经典类是按深度优先来继承的 新式类是按广度优先来继承的;在python3中 经典类和新式类都是按广度优先来继承的。
    class A(object):                   #基类
        def __init__(self):
            print("A")
    
    
    class B(A):
        # def __init__(self):        # B继承A  单继承
        #     print("B")
        pass
    
    class C(A):                    
        # def __init__(self):        # C继承A
        #     print("C")
        pass
    
    class D(B,C):
        #def __init__(self):         #D继承B和C   多继承                  
        #     print("D")       
        pass
    
    a=D()
    继承

    子类继承了父类的所有属性。子类自定义的属性如果和父类的属性重名了,那就直接调用自己的属性,不再调用父类的属性。

    1.1、继承顺序

    Python2中的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先

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

    Python3中统一都是新式类,都是广度优先查找。

    class A(object):
        def test(self):
            print('from A')
    
    class B(A):
        def test(self):
            print('from B')
    
    class C(A):
        def test(self):
            print('from C')
    
    class D(B):
        # def test(self):
            # print('from D')
        pass
    
    class E(C):
        def test(self):
            print('from E')
    
    class F(D,E):
        # def test(self):
        #     print('from F')
        pass
    f1=F()
    f1.test()
    
    # 查找顺序:F --> D --> B --> E --> C --> A
    python3新式类广度优先继承

    python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。

    例如:

    print(F.__mro__)   #打印mro列表
    
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

     1.2、子类中调用父类的方法 

    class People(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def eat(self):
            print("%s is eating" % self.name)
    
        def sleep(self):
            print("%s is sleeping" % self.name)
    
        def print_tab(self):
            print("%s 今年 %s" % (self.name, self.age))
    
    
    class Relation(object):
    
        def make_friend(self, obj):
            print("%s is making friends with %s" % (self.name, obj.name))
    
    
    class Man(Relation, People):  # 继承Relation,和People两个基类
    
        def __init__(self, name, age, money):
            People.__init__(self, name, age)       # 重构经典类写法
            # super(Man,self).__init__(name,age)   # 新式写法
            self.money = money
    
        def drink(self):
            print("%s is drinking %s" % (self.name, self.money))
    
        def sleep(self):        # 基类中也有sleep()方法
            People.sleep(self)  # 重构基类中sleep()方法后   先调用基类的sleep()方法 再调用自己的方法    如果不重构,就调用自己的sleep()方法
            print("man is sleeping")
    
    
    class Women(People, Relation):  # 继承Relation,和People两个基类
    
        def get_birth(self):
            print("%s is making face" % self.name)
    
    
    m1 = Man("Jim", 20, 100)
    m1.drink()
    m1.sleep()
    m1.eat()
    w1 = Women("lucy", 20)
    w1.get_birth()
    
    m1.make_friend(w1)
    View Code
    # -*-coding:utf-8-*-
    
    class school(object):
    
        def __init__(self,name,addr):
            self.name=name
            self.addr=addr
            self.students=[]
            self.teachers=[]
    
        def enroll(self,stu_obj):
            print('为%s学员办理注册手续'%stu_obj.name)
            self.students.append(stu_obj)
    
    
    class SchoolMember(object):
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
    
    
    
    
    
    class Teacher(SchoolMember):
    
        def __init__(self,name,age,sex,salary,course):
            super(Teacher,self).__init__(name,age,sex)
            self.salary=salary
            self.course=course
    
        def tell(self):
            print("""-------info of Teacher:---------
                   name:%s
                   age:%s
                   sex:%s
                   salary:%s
                   course=%s
             """ % (self.name, self.age, self.sex, self.salary, self.course))
    
        def teach(self):
            print("%s is teaching course[%s]"%(self.name,self.course))
    
    
    
    
    
    class Student(SchoolMember):
    
        def __init__(self,name,age,sex,stu_id,grade):
            super(Student,self).__init__(name,age,sex)
            self.stu_id=stu_id
            self.grade=grade
    
        def tell(self):
            print("""-------info of student:---------
                   name:%s
                   age:%s
                   sex:%s
                   stu_id:%s
                   grade=%s
             """ % (self.name, self.age, self.sex, self.stu_id, self.grade))
    
    
    
    
    
        def pay(self,account):
            print("%s paid account:$%d"%(self.name,account))
    
    
    
    school1=school('北京大学','北京')
    
    teacher1=Teacher('李老师',30,'',5000,'Linux')
    teacher2=Teacher('陈老师',23,'',3000,'PHP')
    
    
    student1=Student('小明',23,'',1001,'python')
    student2=Student('小露',25,'',1002,'python')
    
    
    teacher1.tell()
    
    student1.tell()
    
    
    school1.enroll(student1)
    
    print(school1.students)
    
    school1.students[0].pay(5000)
    示例

    2、多态

    多态指的是一类事物有多种形态,指出了对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑他们具体的类。

    一种接口,多种实现 python 不直接支持多态,可以间接实现

    class Animal(object):
        def __init__(self, name):  # Constructor of the class
            self.name = name
    
        # def talk(self):  # Abstract method, defined by convention only
        #     raise NotImplementedError("Subclass must implement abstract method")
        @staticmethod
        def func(obj):  # 一个接口,多种形态
            obj.talk()
    
    class Cat(Animal):
        def talk(self):
            print('%s: 喵喵喵!' % self.name)
    
    
    class Dog(Animal):
        def talk(self):
            print('%s: 汪!汪!汪!' % self.name)
    
    
    c1 = Cat('小晴')
    d1 = Dog('李磊')
    
    Animal.func(c1)
    Animal.func(d1)
    多态

     3、封装

    1、封装的特性:双下划线__开头(私有属性和私有方法),类内部可以调用,外部不可调用。

    注意: 双下划线开头在外部不能被调用是因为被类重新命名了,其实在外部是可以被调用的。

    class Role:
        num = 123  # 类变量,大家都可以调用
        num_list = []
        __info="角色"
        def __init__(self, name, role, weapon, life_value=100, money=15000):
    
            self.name = name  # self.name 赋给实例   实例变量(静态属性)  作用域就是实例本身
            self.role = role
            self.weapon = weapon
            self.__life_value = life_value  # 私有属性前面要加两个下划线__来定义,私有属性只可以在方法里面调用
            self.money = money
    
    
        def shot(self):
            print("shooting...")
    
        def got_shot(self):
            print("ah...,I got shot...",self.__info)
    
    
        def __get_weapon(self):  # 定义私有方法   在定义方法名前加两个下划线,私有方法也是只能在类方法中被调用
            print('私有方法',self.__info)
    
    r=Role("Jim","武器","ak47")
    #print(r.__info)   这样是调用不到的,因为它被类重新命名为_Role__info了
    print(Role.__dict__)
    #双下划线开头在外部不能被调用是因为被类重命名了
    print(r._Role__info)   # 私有属性这样就可以调用了
    r._Role__get_weapon()  # 私有方法这样可以被调用
    封装-私有属性和方法
  • 相关阅读:
    【原】Go语言及Web框架Beego环境无脑搭建
    Treap学习笔记
    读书笔记--Head First PMP目录
    Linux操作系统常用命令合集——第四篇-文件系统权限操作(5个命令)
    Linux操作系统常用命令合集——第三篇-系统管理操作(25个命令)
    Linux操作系统常用命令合集——第二篇- 用户和组操作(15个命令)
    路由器与交换机配置——配置文件和系统映像备份与恢复
    路由器配置——密码重置
    交换机配置——端口安全
    路由器与交换机配置——交换机默认网关(实现跨网段telnet)
  • 原文地址:https://www.cnblogs.com/sunhao96/p/7724032.html
Copyright © 2020-2023  润新知