zoukankan      html  css  js  c++  java
  • Python面向对象编程

    一、什么是面向对象

      面向对象编程(OOP,Object Oriented Programming)
      OOP三个主要的特征:数据封装、继承和多态。
      所有的程序是由一定的属性和行为对象组成的,不同的对象的访问通过函数调用来完成,对象间所有的交流都是通过方法调用,通过对封装对象数据,提高复用率。

    二、创建类和对象

      面向对象编程是一种编程方式,此编程方式的落地需要使用 "类" 和 "对象"来实现,所以,面向对象编程其实就是对 "类" 和 "对象" 的使用。

      类就是一个模板,模板里可包含多个函数,函数里实现一些功能。对象则是根据模板创建的实例,通过实例对象可以执行类中的方法。

    class Role (object):
        def __init__(self,name):
        self.name = name
      
        def buy_weapon(self,weapon):
        pass

      class是关键字,定义一个类,其名称为Role,这个类继承了Python的父类,名为object。在类的下面可以看到有很多函数的定义,但在 class中,函数被称为方法,所以这里暂时在一个名为Role类的下面有__init__和buy_weapon方法。

    三、封装

      封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

      所以,在使用面向对象的封装特性时,需要:1.将内容封装到某处 2.从某处调用被封装的内容

    class Role (object):    #object是父类,继承父类
        def __init__(self,name,role,weapon,life_value):     #称为构造方法,根据类创建对象时自动执行
            self.name = name    #成员变量,self 代表传进来的name,在整个类都可以使用这个变量,把一个局部变量变为了全局变量
            self.role = role
            self.weapon = weapon
            self.life_val = life_value
       
        def buy_weapon(self,weapon):
            print("[%s] is buying [%s]" % (self.name,weapon))
            self.weapon = weapon
       
    # 把一个抽象的类变成一个具体的过程叫实例化
    t1 = Role("Stanley",'Terrorist','Glock',100)    #等价于Role(t1,"Stanley",'Terrorist','b11',100),同时将'Stanley'、'Terrorist'、'Glock'和100封装到t1和self的name、role、weapon、life_value属性中
    p1 = Role("Tom",'Police','Desert Eagle',90) #Role(p1,"Tom",'Police','Desert Eagle',90)
    print("t1's weapon was [%s] before" % t1.weapon)
    print("=".center(40,'='))
    t1.buy_weapon('AK47')    #转换为Role.buy_weapon(t1,'AK47')
    print("t1's weapon is [%s] now" % t1.weapon)
      
    Result:
    t1's weapon was [Glock] before
    ========================================
    [Stanley] is buying [AK47]
    t1's weapon is [AK47] now

      第一个方法__init__是初始化构造方法,构造方法的第一个参数永远是self,表示这个类的对象本身,真正构造对象时,self这个参数不用写,python编译器会自己加上去,构造方法的作用就是对self对象进行赋值,如下面传进来的name赋给self.name,这么做的目的是因为在class中,每个方法依旧是要遵循函数规则的,在函数下面每个变量都是局部变量,在其他函数中并不能相互调用,如此做就把一个局部变量变为全局变量。

      通过self间接调用被封装的内容:

      第二个方法除了编译器会自己加上去的self参数外,weapon参数接收传入的变量,打印调用的参数。在print之后self.name含义是将调用者的name赋值给self。

      接下来要对p1和t1进行实例化,这是将一个抽象的类变成一个具体的过程,生成了p1和t1两个角色。t1 = Role("Stanley",'Terrorist','Glock',100),Python解释器会将此转换为 Role(t1,"Stanley",'Terrorist','Glock',100),这里通过解释器转换后的t1其实就是self。

      现在t1角色进行购买行为,t1.buy_weapon('AK47'),Python解释器会将此转换为 Role.buy_weapon(t1,'AK47'),如上所述此时的t1就是self,也可理解为将t1传入__init__初始化构造方法,就可直接self.name(等价于t1.name)获取到name的变量了(Stanley)。

      综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

    四、继承

      继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容,也可理解为由一般到特殊。

    class SchoolMember(object):
        member_nums = 0
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
            self.enroll()
     
        def enroll(self):
            print("NO.%s SchoolMember [%s] is enrolled!" % (SchoolMember.member_nums,self.name))
            SchoolMember.member_nums += 1   #统计人员数量不可写为self.member_nums += 1,因self实例下没有此变量,两者毫无关联。
     
        def tell(self):
            print("Hello, My name is [%s]" % self.name)
     
    class Teacher(SchoolMember):    #参数为继承对象
        def __init__(self,name,age,sex,course,salary):  #如果不写__init__默认就继承了父类的所有属性,但子类需要额外扩展,需先重写再继承
            super(Teacher,self).__init__(name,age,sex)      #上面进行了重写,再继承回来进行覆盖,推荐新式类语法
            #SchoolMember.__init__(self,name,age,sex)        #此为经典类语法,不推荐
            self.course = course
            self.salary = salary
     
        def teaching(self):
            print("Teacher [%s] is teaching [%s]" % (self.name,self.course))
     
    class Student(SchoolMember):
        def __init__(self,name,age,sex,course,tuition,):
            super(Student,self).__init__(name,age,sex)
            self.course = course
            self.tuition = tuition
     
        def pay_tuition(self):
            print("Student [%s] pays tuition [%s] again" % (self.name,self.tuition))
     
    #实例化老师
    t1 = Teacher('Stanley',24,'M','Python',1000)    #实例化,不可实例化SchoolMember,其只可用来继承
    t1 = Teacher('Katrina',29,'M','MySQL',1500)    #实例化,不可实例化SchoolMember,其只可用来继承
    #实例化学生
    s1 = Student('Tim',24,'F','MySQL',10000)
    s2 = Student('Bella',27,'M','Python',12000)
    print("===========子类使用父类方法============")
    t1.tell()
    s1.tell()
    print("===========子类使用私有方法============")
    t1.teaching()
    s1.pay_tuition()
     
    Result:
    NO.0 SchoolMember [Stanley] is enrolled!
    NO.1 SchoolMember [Katrina] is enrolled!
    NO.2 SchoolMember [Tim] is enrolled!
    NO.3 SchoolMember [Bella] is enrolled!
    ===========子类使用父类方法============
    Hello, My name is [Katrina]
    Hello, My name is [Tim]
    ===========子类使用私有方法============
    Teacher [Katrina] is teaching [MySQL]
    Student [Tim] pays tuition [10000] again

      此为标准继承示例,其中包含三个类,SchoolMember是父类,Teacher和Student是子类,子类中拥有父类的共同属性,除此之外,子类还需要额外进行扩展,所以在子类中要先重写,再从父类继承回来进行覆盖。在继承语法中super为关键字,不可省略,其参数为子类名称,self,__init__参数为需要继承的属性。相关封装特性详见上一段落,不再累述。父类和子类定义好后,实例化Teacher和 Student,在父类中执行注册方法,每个子类都可调用父类的tell方法,并且每个子类都会包含私有方法teaching和pay_tuition,这就利用继承特性实现了简单的权限限制功能。

      综上所述,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

    五、多态

      多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

      Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中的。那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

      通过Python模拟的多态:

    class Animal:
        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")
     
    class Cat(Animal):
        def talk(self):
            return 'Meow!'
     
    class Dog(Animal):
        def talk(self):
            return 'Woof! Woof!'
     
    animals = [Cat('Missy'),
               Dog('Lassie')]
     
    for animal in animals:
        print animal.name + ': ' + animal.talk()
  • 相关阅读:
    SQL-排名函数
    SQL-简单查询
    SQL-判断表是否存在
    HDU1557权利选举
    Bresenham画直线,任意斜率
    LCS最长公共子序列HDU1159
    zoj1276矩阵连乘dp
    OJ的文件流操作
    dp题目
    翻纸牌 高校俱乐部 英雄会 csdn
  • 原文地址:https://www.cnblogs.com/stefan-liu/p/5272850.html
Copyright © 2011-2022 走看看