python笔记七:面向对象编程(OOP)——三大特性

一.面向对象的三大特性

1.封装

  • 封装就是对对象成员进行访问控制

  • 封装的三个级别:

            - 公开:public

            - 受保护的:protected

            - 私有的:private

              (public、protected、private都不是关键字)

  • 判断对象的位置:

            - 对象内部

            - 对象外部

            - 子类中

  • 私有:private

            - 私有成员是最高级别的封装,只能在当前类或者对象中访问

            - 封装方法:在成员前面添加两个下划线即可

注:python的私有不是真的私有,只是一种改名策略,可以使用对象._classname_attributename访问

class Person():
    name = 'liu'  #name是共有的成员
    __age = 18  #age是私有成员

p = Person()
print(p.name)
print(p.__age)  #报错,没有这个变量

   

***通过__dict__查看所有对象得:

print(Person.__dict__)

***用改后的名字可以访问

p = Person()
print(p.name)
#print(p.__age)  #报错,没有这个变量
p._Person__age=19
print(p._Person__age)

   

  • 受保护的:protected

            - 受保护的封装是将对象成员进行一定级别的封装,然后在类或者子类中都可以进行访问,但在外部不可以

            - 封装方法:在成员名称前添加一个下划线

  • 公开的:public

            - 公开的封装对成员没有任何操作,任何地方都可以访问


2.继承

  • 继承就是一个类可以获得另一个类中的成员属性和成员方法

            - 人:姓名、年龄、吃、睡(父类)

            - 老师:继承人的成员属性和方法,再定义自已单独的成员属性和方法即可(子类)

  • 作用:减少代码,增加代码的复用功能,可以设置类与类之间的关系
  • 继承与被继承:

            - 被继承的类叫父类、基类、超类,     用于继承的类叫子类、派生类

            - 继承与被继承一定存在一个 is-a 的关系

  • 继承的特征:

            - 所有的类都继承自object类

            - 自类继承父类后,可以使用父类除私有成员外的所有内容(可以继承公共的和受保护的)

            - 子类继承父类后并没有将父类成员完全赋值到子类中,而是通过引用关系访问调用

            - 子类中可以定义独有的成员属性和方法

            - 子类中定义的成员和父类相同时,优先使用子类成员

            - 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用,可以使用  父类名.父类成员  的格式来调用父类成员,也可以使用  super().父类成员  的格式来调用

class Person():
    name = 'NoName'
    age = 18
    _petname = 'sec' #小名是受保护的,子类可以用,但不能公用
    __score = 0 #考试成绩是私有的,只能自己知道
    def sleep(self):
        print('sleep')

    def work(self):
        print('make some money')

class Teacher(Person): #父类写在括号里,除父类的私有属性,其他都被子类继承
    id = '123456'
    name = 'liu'  #子类的成员变量与父类相同了

    def make_test(self):
        print('you have a test today')

    def work(self):   #扩充父类的功能,只需要调用父类相应的函数
        Person.work(self)  #可以用 super().work() 代替
        self.make_test()


t = Teacher()
print(t.name)    #自类继承父类的公共成员,但与父类成员变量同名时优先使用子类成员变量
print(t._petname)  #子类继承父类受保护的成员
t.sleep()  #子类继承父类的方法
#print(t.__score)  #报错,子类不能继承父类的私有成员变量

print('*'*20)

t.work()  #扩充父类功能

   

  • 构造函数

            - 是一类特殊的函数,在类进行实例化之前自动调用

            - 构造函数必须有一个self参数,self不是关键字,名字可以不是self但必须有

class Dog():
    def __init__(self):  # __init__就是构造函数,每次实例化的时候第一个被自动调用,主要工作是初始化
        print('i am a dog')
        self.name = 'xiaobai'
        self.age = 2
        
d = Dog()

   

  • 继承变量函数的查找顺序问题

            - 优先查找自己的变量

            - 没有则查找父类

            - 构造函数如果本类中没有定义,则自动查找调用父类构造函数,直到找到为止,如果本类有定义,则不再继续向上查找

            - 如果子类没定义,父类的构造函数含参数,则构造对象时的参数应该按父类参数来构造

class Animel():
    def __init__(self):
        print('i am an animel')

class PaXingAni(Animel):
    def __init__(self,name):  ####如果没有self只有name参数时报错,self换成其他的名字也不会报错
        print('{} is a paxingAni'.format(name))

class Dog(PaXingAni):
    def __init__(self):  #__init__就是构造函数,每次实例化的时候第一个被自动调用,主要工作是初始化
        print('i am a dog')

class Cat(PaXingAni):
    pass


d = Dog()
c = Cat('kkk')  #如果不传参数则报错

   

  • super

            - super不是关键字,而是一个类

            - super的作用是获取MRO(method resolustion order)列表中的第一个类,这个类一般就是父类

            - super和父类直接没有任何实质性关系,但是通过super可以调用到父类

            - super使用的两个方法,参见在构造函数中调用父类的构造函数

#扩充父类的构造函数例子一:
#使用super调用
class PaXingAni():
    def __init__(self,name):  ####如果没有self只有name参数时报错,self换成其他的名字也不会报错
        print('hhh',name)

class Dog(PaXingAni):
    def __init__(self,name):  #__init__就是构造函数,每次实例化的时候第一个被自动调用,主要工作是初始化
        super(Dog,self).__init__(name) #或super().__init__(name) 
        print('dog的附加功能')

d = Dog('kkk')

   

#扩充父类的构造函数例子二:
#调用父类名改变
class PaXingAni():
    def __init__(self,name):  ####如果没有self只有name参数时报错,self换成其他的名字也不会报错
        print('hhh',name)

class Dog(PaXingAni):
    def __init__(self,name):  #__init__就是构造函数,每次实例化的时候第一个被自动调用,主要工作是初始化
        PaXingAni.__init__(self,name)
        print('dog的附加功能')

d = Dog('kkk')

   

  • 单继承和多继承

            - 单继承:每个类只能继承一个类(只有一个父类)

                      优点:逻辑清晰,简单

                      缺点:功能不能无限扩展,只能在当前唯一的继承链中扩展

            - 多继承:每个类允许继承多各类

                      优点:功能扩展方便

                      缺点:继承关系混乱

#继承的例子
class Fish():
    def __init__(self,name):
        self.name = name
    def swim(self):
        print('swim')

class Bird():
    def __init__(self,name):
        self.name = name
    def fly(self):
        print('fly')

class SuperMan(Fish,Bird):
    def __init__(self,name):
        self.name = name

liu = SuperMan('hhh')
liu.swim()

菱形继承/钻石继承:多个子类继承同一个父类,这些子类又被同一个类继承

#菱形继承
class A():
    pass

class B(A):
    pass

class C(A):
    pass

class D(B,C):
    pass

多继承的MRO:MRO是多继承中用于保存继承顺序的列表,python用C3算法计算

MRO列表计算原则:

  子类永远在父类前

  如果多个父类,根据继承语法括号中书写的顺序

  如果多个类继承与同一个父类,孙子类中只会选取括号中第一个父类的父类


3.多态

  • 多态就是一个对象在不同情况下有不同的状态出现
  • 多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数
  • python中多态不是语法,是一种设计思想
  • 多态:同一事物的不同形态,比如动物分为人、狗、猫
  • Mixin设计模式:主要采用多继承方式对类进行扩展

Mixin实现多继承时:

  -首先它表示某一单一功能,而不是某一物品

  -职责必须单一,如果有多个功能则写多个Mixin

  -Mixin不依赖于子类的实现

  -子类即使没有继承Mixin功能也照样工作,只是缺少了某个功能

Mixin优点:

  -可以在不对类修改的前提下扩充功能

  -避免创建很多类,导致类继承混乱

#
class Person():
    name = 'xiaobai'
    age = 2
    def eat(self):
        print('eat******')
    def drink(self):
        print('drink******')

class Teacher(Person):
    def work(self):
        print('work******')

class Student(Person):
    def study(self):
        print('study******')

class Tutor(Teacher,Student):
    pass

t = Tutor()
print(t.__dict__)
print(Tutor.__mro__)
print(Tutor.__dict__)

print('*'*20)
#Mixin的写法
class TeacherMixin():  #老师和学生没有父类
    def work(self):
        print('work')

class StudentMixin():
    def study(self):
        print('study')

class TutorM(Person,TeacherMixin,StudentMixin):
    pass

tt = TutorM()
print(tt.__dict__)
print(TutorM.__mro__)
print(TutorM.__dict__)


4.类的函数

  • issubclass:检测一个类是否是另一个类的子类

class A():
    pass
class B(A):
    pass
class C():
    pass

print(issubclass(B,A))
print(issubclass(C,A))
print(issubclass(C,object))

   

  • isinstance:检测一个对象是否是一个类的实例
class A():
    pass

a = A()
print(isinstance(a,A))

   

  • hasattr:检测一个对象是否有成员***
class A():
    name = 'liu'

a = A()
print(hasattr(a,'name'))

   

  • getattr: get attribute
  • setattr:set attribute
  • delattr:delete attribute
help(setattr)

  • dir :获取对象成员列表
class A():
    name = 'liu'

a = A()
print(dir(a))


视频参考图灵学院

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值