6-Python-面向对象

来源:互联网 发布:南风知我意琰阙 编辑:程序博客网 时间:2024/05/18 01:28
  1. 知识点
    1. 知识点
    2. --Python-面向对象

  2.  类
    1. 定义类
    2. 定义一个类,格式如下:
      1. class 类名:
      2. 属性列表
      3. 方法列表
    3. 创建对象的格式为:
      1. 对象名 = 类名()
    4. 注意点:
      1. 提示找不到该属性,因为私有属性是不能够在类外通过对象名来进行访问的。在Python中没有像C++中publicprivate这些关键字来区别公有属性和私有属性,它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。

  3.  self
    1. 小总结
    2. 所谓的self,可以理解为自己
    3. 可以把它当做C++中类里面的this指针一样理解,就是对象自身的意思,在用某个对象调用该方法时,就将该对象作为第一个参数传递给self
  4.  构造器
    1. <1>构造器方法的格式
    2. "构造器"方法,的格式如下:
      1. def __init__():
    3. <2>构造器方法调用
    4. Car类中添加 "构造器"方法:
      1. # 定义类
      2. class Car:
      3. # 构造器方法
      4. def __init__(self):
      5. self.wheelNum = 4
      6. self.color = 'blue'
      7. # 方法
      8. def run(self):
      9. print '车在跑,目标:夏威夷'
      10. # 创建对象
      11. BMW = Car()
      12. print('车的颜色为:%s'%BMW.color)
      13. print('车轮子数量为:%d'%BMW.wheelNum)

    5. 小总结
    6. 通过上面的列子能够看到,当创建完Car类型的对象后,对象BMW对象的成员变量wheelNumcolor都发生了变化,因此__init__()方法是在创建对象后,被默认执行了
    7. 想一想:
    8. 既然在创建完对象后__init__()方法已经被默认的执行了,那么能否让对象在默认调用__init__()方法的时候传递一些参数呢?如果可以,那怎样传递呢?
      1. # 定义类
      2. class Car:
      3. # 构造器方法
      4. def __init__(self, newWheelNum, newColor):
      5. self.wheelNum = newWheelNum
      6. self.color = newColor
      7. # 方法
      8. def run(self):
      9. print '车在跑,目标:夏威夷'
      10. # 创建对象
      11. BMW = Car(4, 'green')
      12. print '车的颜色为:',BMW.color
      13. print '车轮子数量为:',BMW.wheelNum

    9. <3>总结
      1. 构造器方法,在创建一个对象时默认被调用,不需要手动调用


  5.  析构&继承
    1. 析构
    2. 创建对象时,默认调用构造方法;当删除一个对象时,同样也会默认调用一个方法,这个方法为析构方法
    3. <1>析构方法(__del__())
    4. demo:
      1. class Animal():
      2. # 构造方法
      3. def __init__(self):
      4. print '---构造方法被调用---'
      5. # 析构方法
      6. def __del__(self):
      7. print '---析构方法被调用---'
      8. # 创建对象
      9. dog = Animal()
      10. # 删除对象
      11. del dog
      结果:

    5. 构造和析构
      1. <2>继承示例
        1. # 定义一个父类,如下:
        2. class Cat:
        3. name = '猫'
        4. color = 'white'
        5. def run(self):
        6. print self.name,'--在跑'
        7. # 定义一个子类,如下:
        8. class Bosi(Cat):
        9. def setName(self, newName):
        10. self.name = newName
        11. def eat(self):
        12. print self.name,'--在吃'
        13. bs = Bosi()
        14. print 'bs的名字为:',bs.name
        15. print 'bs的颜色为:',bs.color
        16. bs.eat()
        17. bs.setName('波斯')
        18. bs.run()

      2. 运行结果:
      3. 继承
      4. 说明:
      5. 虽然子类,没有构造方法,但是父类有,所以在子类继承父类的时候,其构造方法也会被继承,所以只要创建Bosi的实例对象,就默认执行了那个继承过来的构造方法

      6. 小总结:
        1. 子类在继承的时候,在定义类时,小括号()中为父类的名字
        2. 父类的属性、方法,会被继承给子类



  6.  多继承
    1. Python中多继承的格式如下:
      1. # 定义一个父类
      2. class A:
      3. def printA(self):
      4. print '----A----'
      5. # 定义一个父类
      6. class B:
      7. def printB(self):
      8. print '----B----'
      9. # 定义一个子类,继承自A、B
      10. class C(A,B):
      11. def printC(self):
      12. print '----C----'
      13. obj_C = C()
      14. obj_C.printA()
      15. obj_C.printB()

    2. 运行结果:
      1. ----A----
      2. ----B----

    3. *说明
      1. python中是可以多继承的
      2. 父类中的方法、属性,子类会继承


    4. <2>注意点
    5. 想一想:
      1. 如果在上面的多继承例子中,如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,调用哪个?

    6. 答:




  7.  重载
    1. 1. 重载
    2. 所谓重载,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
      1. #coding=utf-8
      2. class Cat:
      3. def sayHello(self):
      4. print("halou-----1")
      5. class Bosi(Cat):
      6. def sayHello(self):
      7. print("halou-----2")
      8. bosi = Bosi()
      9. bosi.sayHello()

    3. 2. 调用父类的方法
      1. #coding=utf-8
      2. class Cat:
      3. def __init__(self,name):
      4. self.name = name
      5. self.color = 'yellow'
      6. class Bosi(Cat):
      7. def __init__(self,name):
      8. Cat.__init__(self,name) # 调用父类的__init__方法
      9. def getName(self):
      10. return self.name
      11. bosi = Bosi('xiaohua')
      12. print(bosi.name)
      13. print(bosi.color)


  8.  多态
    1. 多态
    2. 多态的概念是应用于JavaC#这一类强类型语言中,而Python崇尚“鸭子类型”。
    3. 所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
    4. Python伪代码实现JavaC#的多态
      1. class F1:
      2. pass
      3. class S1(F1):
      4. def show(self):
      5. print 'S1.show'
      6. class S2(F1):
      7. def show(self):
      8. print 'S2.show'

    5. # 由于在Java或C#中定义函数参数时,必须指定参数的类型
    6. # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
    7. # 而实际传入的参数是:S1对象和S2对象
      1. def Func(F1 obj):
      2. """Func函数需要接收一个F1类型或者F1子类的类型"""
      3. print obj.show()
      4. s1_obj = S1()
      5. Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
      6. s2_obj = S2()
      7. Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show


    8. Python “鸭子类型”
      1. class F1:
      2. pass
      3. class S1(F1):
      4. def show(self):
      5. print 'S1.show'
      6. class S2(F1):
      7. def show(self):
      8. print 'S2.show'
      9. def Func(obj):
      10. print obj.show()
      11. s1_obj = S1()
      12. Func(s1_obj)
      13. s2_obj = S2()
      14. Func(s2_obj)


  9. 类属性、实例属性
    1. 类属性、实例属性
    2. 在了解了类基本的东西之后,下面看一下python中这几个概念的区别
    3. 先来谈一下类属性和实例属性
    4. 在前面的例子中我们接触到的就是类属性,顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个C++中类的静态成员变量有点类似对于公有的类属性,在类外可以通过类对象和实例对象访问
    5. 类属性
      1. class people:
      2. name = 'Tom' #公有的类属性
      3. __age = 12 #私有的类属性
      4. p = people()
      5. print p.name #正确
      6. print people.name #正确
      7. print p.__age #错误,不能在类外通过实例对象访问私有的类属性
      8. print people.__age #错误,不能在类外通过类对象访问私有的类属性


    6. 实例属性
    7. 实例属性是不需要在类中显示定义的,比如:
      1. class people:
      2. name = 'Tom'
      3. p = people()
      4. p.age =12
      5. print p.name #正确
      6. print p.age #正确
      7. print people.name #正确
      8. print people.age #错误

    8. 在类外对类对象people进行实例化之后,产生了一个实例对象p,然后p.age = 12这句给p添加了一个实例属性age,赋值为12。这个实例属性是实例对象p所特有的,注意,类对象people并不拥有它(所以不能通过类对象来访问这个age属性)。当然还可以在实例化对象的时候给age赋值
      1. class people:
      2. name = 'Tom'
      3. #__init__()是内置的构造方法,在实例化对象时自动调用
      4. def __init__(self,age):
      5. self.age = age
      6. p = people(12)
      7. print p.name #正确
      8. print p.age #正确
      9. print people.name #正确
      10. print people.age #错误

    9. 如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
      1. class people:
      2. country = 'china'
      3. print people.country
      4. p = people()
      5. print p.country
      6. p.country = 'japan'
      7. print p.country #实例属性会屏蔽掉同名的类属性
      8. print people.country
      9. del p.country #删除实例属性
      10. print p.country


    10. 总结
    11. 对于类属性和实例属性,如果在类方法中引用某个属性,该属性必定是类属性,而如果在实例方法中引用某个属性(不作更改),并且存在同名的类属性,此时若实例对象有该名称的实例属性,则实例属性会屏蔽类属性,即引用的是实例属性,若实例对象没有该名称的实例属性,则引用的是类属性;如果在实例方法更改某个属性,并且存在同名的类属性,此时若实例对象有该名称的实例属性,则修改的是实例属性,若实例对象没有该名称的实例属性,则会创建一个同名称的实例属性。想要修改类属性,如果在类外,可以通过类对象修改,如果在类里面,只有在类方法中进行修改。

  10.  静态方法和类方法
    1. 静态方法和类方法
    2. 1. 类方法
    3. 是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,就最好用'cls'了),能够通过实例对象和类对象去访问。
      1. class people:
      2. country = 'china'
      3. #类方法,用classmethod来进行修饰
      4. @classmethod
      5. def getCountry(cls):
      6. return cls.country
      7. p = people()
      8. print p.getCountry() #可以用过实例对象引用
      9. print people.getCountry() #可以通过类对象引用

    4. 类方法还有一个用途就是可以对类属性进行修改:
      1. class people:
      2. country = 'china'
      3. #类方法,用classmethod来进行修饰
      4.  
      5. @classmethod
      6. def getCountry(cls):
      7. return cls.country
      8. @classmethod
      9. def setCountry(cls,country):
      10. cls.country = country
      11. p = people()
      12. print p.getCountry() #可以用过实例对象引用
      13. print people.getCountry() #可以通过类对象引用
      14. p.setCountry('japan') 
      15. print p.getCountry()
      16. print people.getCountry()

    5. 结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变
    6. 2. 静态方法
    7. 需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数
      1. class people:
      2. country = 'china'
      3. @staticmethod
      4. #静态方法
      5. def getCountry():
      6. return people.country
      7. print people.getCountry()

    8. 总结
      1. 从类方法和实例方法以及静态方法的定义形式就可以看出来,
      2. 类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;
      3. 而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。
      4. 静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用