• Python面向对象编程-类的封装,继承、多态


    面向对象是一种程序设计思想,对象作为程序基本单元,包含了数据和操作数据的函数。

    面向对象的三大特点--数据封装、多态和继承。

    #类的创建,class关键字,类名大写,object表示从哪个类继承而来,如果没有继承的类,默认就是object,这是所有的类都会继承的类
    
    class Student(object):
        pass

    创建类的实例

    1 tom = Student()  #tom实例指向类Student

    还可以自由的为实例绑定属性

    tom.age = 18
    tom.sex = boy

    #访问实例属性
    >>>tom.age
    18
    >>>tom.sex
    'boy'

    类是一个模板,可以在创建类的同时将实例的属性绑定

    class Student(object):
        def __init__(self,name,age,sex):  #__init__方法可以将实例属性绑定,第一个参数永远是self,表示实例本身,这样,age、sex属性绑定后指向实例本身
         self.name=name        
    self.age
    =age self.sex=sex

    使用__init__方法后,再去创建实例时,属性就不允许为空,否则提示丢失需求参数

    tom = Student('tom',20,'boy')
    >>>tom.name
    tom
    >>>tom.age
    20
    >>>tom.sex
    'boy'

    >>>tom = Student()
    TypeError: __init__() missing 3 required positional arguments: 'name', 'age', and 'sex'

    实例的属性可以在外部随意访问,也可以再外部定义一个函数用来访问类实例全部的属性。

    #外部直接访问
    >>>print(tom.name)
    tom
    ......

    #外部函数访问
    def
    info(stu): print('%s %d %s ' %(stu.name,stu.age,stu.sex)) >>>tom = Student('tom',20,'boy')


    >>>info(tom)

    tom
    20 

    boy

     

    数据封装

    像上面在外部定义访问函数不是不可以的。但类本身具有这些属性,直接在类内部写出打印函数就行  这样就实现了数据的封装。

    完整的封装

    class Student(object):
        def __init__(self,name,age,sex):
                self.name=name
                self.age=age
                self.sex=sex
        def info(self):
                print('%s
    %d
    %s' %(self.name,self.age,self.sex))
    
    
    tom = Student('tom',20,'boy')
    
    >>>tom.info()
    tom
    20
    boy

    这样写出来,对象属性及操作方法对外隐藏了,调用很简单。

    同时封装的好处就是可以为类增加新的方法,比如内部定义一个函数来判定学生属于的班级。

    class Student(object):
        def __init__(self,name,stunum):
                self.name=name
                self.stunum=stunum
    
        def info(self):
                print('%s%s' %(self.name,self.stunum))
    
        def attclass(self):   #新增加的方法,根据学号判断所属班级
                if self.stunum > 0 and self.stunum <= 50:
                    print("class one")
                if self.stunum > 50 and self.stunum <=100:
                    print("class two")
                print("class three")

    >>>tom = Student('tom',56)
    >>>tom.info()
    tom
    56
    >>>tom.attclass()
    class two

     

     

    私有变量

    从上面的代码看,不仅在外部可以直接访问实例的属性,还可以随便的更改实例的属性,如何使属性变成私有属性,不能随便更改和访问?

    要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private)

    class Student(object):
        def __init__(self,name,num,age,sex):
            self.__name=name  #声明为私有变量,下同
            self.__num=num
            self.__age=age
            self.__sex=sex
    
        def print_std(self):
            print('name:%s
    stunum:%d
    age:%d
    sex:%s
    ' %(self.__name,self.__num,self.__age,self.__sex))
    
        def attclass(self):
            if self.__num >0 and self.__num <= 50:
                print('class one')
            elif self.__num >50 and self.__num <= 100:
                print('class two')
            else:
                print('class three')
    
    tom = Student('tom',65,20,'boy')
    
    tom.num=20  ###私有变量外部更改失效,失效不会有错误提示,编译器直接略过
    
    tom.print_std()
    
    tom.attclass()
    print(tom.__name)#访问时报错,AttributeError: 'Student' object has no attribute '__name'

    如果想要外部代码拿到属性怎么做?

    为类增加一个函数,函数直接返回实例属性

    class Student(object):
        pass
        
        def get_name(self):
                return self.__name
        def get...():
           return .....

    如何允许外部代码修改属性?

    为类增加一个函数,函数参数添加上要修改的属性,这样设置不仅可以避免参数的无效,还可以增加方法约束参数。

    class Student(object):
        pass
    
        def set_name(self,name):
                self.__name=name
        .....
    
    
    >>>tom = Student('tom'..)
    
    >>>tom.set_name('jerry')
    
    >>>print(tom.get_name())
    jerry

     所以,总结下来:

    当类的属性没有声明为私有变量时,类的方法(内部函数)可以修改和访问;外部实例和函数可以随便修改访问。

    当类的属性声明为私有变量时,类的方法可以修改和访问;外部实例和函数无法修改和访问。

    在Python中,当有__xxx__,以双下划线开头并以双下划线结束的变量名称时,是可以访问的,所以,不要和私有的变量命名方式混淆了。

    当类中定义有以单下划线开头的变量时,如_num这样的,是可以外部访问的,但是按照规范来说,最好是不要在外部访问。

     不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:tom._Student_name

    类的继承

    当已有定义好的父类时,再去定义一个类就可以从已定义好的继承,叫做子类。

    继承最大的好处就是父类的方法被子类全部继承

    class Food(object):
        def color(self):
            print('yello')
    
    
    class Banana(Food):
        pass

    >>>ban=Banana()#创建Banana实例
    >>>ban.color()
    yellow

    同时可以自己定义子类的其他方法

    class Banana(Food):
        def feture(self,fet):
                self.fet=fet
    
    >>>ban=Banana()
    
    >>>ban.feture('sweet')
    >>>ban.fet
    sweet

    当子类与父类方法相同时,父类方法被覆盖。

    class Food(object):
        def color(self):
            print('yellow')
    
    
    class Banana(Food):
        def color(self):
             print('good')
    
    >>>ban=Banana()
    >>>ban.color()
    good

    这样就得到了继承的另一个好处,多态。

    Python允许多重继承,

    class Person(class1,class2....):

      pass

    子类拥有所有父类的功能。

    多态

    当定义一个类时,就是定义了一种数据类型,使用isinstance()判断,实例ban即属于Banana类型,又属于Food类型,方向向上,反之不行。香蕉是食物,食物不一定是香蕉。

    class Person(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def say(self):
            print('i am %s' %self.name)
    
    class Student(Person):
        def __init__(self,name,age):
                self.name=name
                self.age=age
    
        def info(self):
                print('%s
    %d
    ' %(self.name,self.age))
    
    def info_pr(name):
        return name.say()
    
    >>>tom = Student('tom',20)
    
    >>>info_pr(tom)
    i am tom

    方法调用将作用在name的实际类型上,先查找Student自身的定义,找不随继承树向上查找,直到找到方法后停止。

    对于静态语言而言,想要传入Person类型,必须是Person或者Person的子类,不然无法使用say()方法

    对于动态语言,只要传入的对象有say()的方法。


    动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。

    Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。

    实例属性和类的属性

    给实例绑定属性是通过实例变量或者self绑定,而给类绑定属性实在class中直接定义的。

    class Student(student):
        name='Student'
        pass
    
    
    
    #通过这种方式绑定类的属性,外部的实例是可以修改和访问的,如果实例属性和类的属性名称一致时,实例的优先级时大于类的属性的,外部访问先寻找实例属性,找不到再去寻找类的属性。
    >>>s = Student()
    >>>print(s.name)
    Student

    >>>print(Student.name)打印类的name属性
    Student

    >>>s.name='tom' 给实例的name属性绑定‘tom’
    >>>print(s.name)
    tom

    >>>print(Student.name)
    Student #类的属性依然存在
  • 相关阅读:
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(6)--结合基于客户端和基于浏览器的控件
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(5)--检查设计方案
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(4)--考虑的因素
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(3)--你的SP版本
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(2)--数据在哪里?
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵(1)--表单模板
    一步步学习微软InfoPath2010和SP2010--第二章节--表单需求:使用决策矩阵
    一步步学习微软InfoPath2010和SP2010--第一章节--介绍InfoPath2010(10)--关键点
    一步步学习微软InfoPath2010和SP2010--第一章节--介绍InfoPath2010(9)--导出模板
    宋浩《概率论与数理统计》笔记---4.2.1、方差的定义
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7645989.html
Copyright © 2020-2023  润新知