• python入门(十三):面向对象(继承、重写、公有、私有)


    1、 三种类定义的写法

     class P1:#定义类   加不加()都可以
        pass
     

    class P2():                    #带(),且括号中为空,类定义

        pass


    class P3(object):  #带括号,且写有object,类定义

        pass


    p1=P1()                    #实例化

    p2=P2()                    #实例化

    p3=P3()                    #实例化

    print(p1)

    print(p2)

    print(p3)

    运行结果:

    E:>python a.py

    <__main__.P1 object at 0x00000219A4A604E0>

    <__main__.P2 object at 0x00000219A4A60518>

    <__main__.P3 object at 0x00000219A4A60550>

    2、类的好处:

    可以把数据放在类的实例里面去管理,使用类里面的实例方法来管理这些数据,保证数据的安全性。

     class Person:

        def __init__(self,name,age):
            if isinstance(age,int) and age >0:
                self.age = age
            else:
                self.age = 0
            self.name = name
            

        def set_age(self,age):
            if isinstance(age,int) and age >0:
                self.age = age

        def get_age(self):
            return self.age

    p1=Person("wulaoshi",18)    #实例化
    p2=Person("lilaoshi",28)    #实例化
    print(p1.age)    #打印实例p1中的age,为18

    p1.age=-100                       #可以使用这种p1.age方式,赋值

    print(p1.age)                        #打印实例p1的age为-100

    print(p2.age)                        #打印实例p2中的age为-1

    p1.set_age(-10)                     #试图通过方法set_age更改p1.age的值为-10

    print(p1.get_age())                   #打印盘p1.age的值

    p2.set_age(28)                      #试图通过方法set_age更改p2.age的值为-10

    print(p2.get_age())                   #打印盘p2.age的值

    运行结果:

    E:>python a.py

    18

    -100                             # p1.age=-100的形式可以赋值成功,可见不安全性

    0                                  #由于实例化时,输入的age值不符合条件,所以

                                       #被强制赋值为0

    -100                               # 设置年龄-10不满足条件,未设置成功,保留原

    28                                 # p2.set_age(28)  设置成功,数据有变化

    3、私有变量:防止数据绕过实例方法被修改
     class Person:

        def __init__(self,name,age):    #该方法表示在实例化的时候会执行
            if isinstance(age,int) and age >0:    #也就是会在实例化的时候进行判断从而赋值
                self.__age = age
            else:
                self.__age = 0
            self.name = name
            

        def set_age(self,age):
            if isinstance(age,int) and age >0:
                self.__age = age

        def get_age(self):
            return self.__age

    p1=Person("wulaoshi",18)

    p2=Person("lilaoshi",-1)

    print(p1.__age)                     #试图在外部访问私有变量

    p1.__age=-100                     #将变量p1.__age赋值为-100

    print(p1.__age)                     #打印变量p1.__age的值

    print(p1.get_age())                  #打印真实的实例p1的age

    运行结果:

    E:>python a.py

    Traceback (most recent call last):

      File "a.py", line 19, in <module>

        print(p1.__age)

    AttributeError: 'Person' object has no attribute '__age'     #证明了p1.__age私有变量不可访问

    -100                                               #p1.__age=-100的真实含义是:将-100赋值给了p1.__age这个变量,此时p1.__age并不是实例p1中的age,两者是不同的

    18                                                 #查看实例p1中的age,显示还是18.证明了私有变量在外部不可改变,并且p1.__age=-100仅仅是给变量p1.__age赋值而已

     
     类的必要组成元素:类里面要有数据,还有操作数据的方法(设定操作数据的规则)
     
    4、私有方法

    1) 内部调用私有方法:

     class Person:

        def __init__(self,name,age):
            if isinstance(age,int) and age >0:
                self.__age = age
            else:
                self.__age = 0
            self.name = name#name是局部变量,self.name是私有变量,局部变量出去这个函数就不能用了,只能在__init__中使用,实例变量在类中的所有方法都能使用这个变量
        def set_age(self,age):
            if isinstance(age,int) and age >0:
                self.__age = age
        def __print_age(self):     #打印年龄的私有方法
            print(self.__age)

        def get_age(self):
            self.__print_age()    #调用私有方法,前面也需要加一个self,私有方法在类的其他的方法中调用
            return self.__age

    p1=Person("wulaoshi",18)
    p2=Person("lilaoshi",28)

    p1.get_age()

    运行结果:

    E:>python a.py

    18                                #会打印出年龄,表示私有方法调用成功

    2) 外部调用私有方法:

    p1.__print_age()    #外部调用私有方法

    运行结果;

    E:>python a.py

    Traceback (most recent call last):

      File "a.py", line 23, in <module>

        p1.__print_age()

    AttributeError: 'Person' object has no attribute '__print_age'

     
    5、类的内置方法:
    __init__  python内置方法
     
     >>> class P:  #定义一个类P
    ...     pass
    ...
    >>> p=P()    #实例化
    >>> dir(p)    #查看类的内置方法
    ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__form
    at__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_s
    ubclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__',
     '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclas
    shook__', '__weakref__']

    前面有__的都是内置方法,有特定的用途

    >>> p.__class__
    <class '__main__.P'>
    >>>
     
    6、方法调用过程与内存的关系
     class Person:

        def __init__(self,name):
            self.name = name

        def get_name(self):#实例方法
            print(self.name)
            


    p1=Person("wulaoshi")
    p1.get_name()


    内存:

    类Person放在内存地址:xxxxyyy1

    类中的方法get_name():也在这个地址中,并且在调用时要有一个参数self

    类变量也在这个地址中

    实例p1放在内存地址:mmmmzzz2

    这个地址中存有数据name="wulaoshi"

    p1.get_name()的调用过程:

    1) 在类的地址xxxxyyy1中先把get_name()的内容找出来想去调用

    2) 实例变量p1的内存地址--->self=mmmmzzzz2

    3) get_name(self=mmmmzzzz2)

    4) 执行方法体:print(self.name)

    5) 去mmmmzzz2找到name的值,然后打印

    总结:

    类中的实例方法中的第一个参数self,实际上就是实例所在内存的地址,通过这个地址,可以找到实例方法中需要使用的各种实例属性(数据)。

     
     class Person:

        def __init__(self,name):
            self.name = name

        def get_name(self):#实例方法
            print(self.name)
        
        def get_name2(self):#实例方法
            print(self.name,self.name)   


    p1=Person("wulaoshi")  #mmmmzzzz2
    p1.get_name()  #self就是p1的内存地址
    p1.get_name2() #self就是p1的内存地址

    p2=Person("李老师")    #mmmmzzzz3
    p2.get_name()  ##self就是p2的内存地址
    p2.get_name2() #self就是p2的内存地址
     
    7、类变量
     class Person:
        x=0  #类变量    #类变量,定义在方法外面,没有self;类变量一般用来计数,比如创建了多少个实例

        def __init__(self,name):    #构造函数只有在实例化的时候才会被执行
            self.name = name
            Person.x+=1

        def get_name(self):#实例方法
            print(self.name)

    p1=Person("wulaoshi")  )#实例化:类名+(参数)
    p2=Person("laoli")
    p3=Person("laoli")

    print(Person.x)           #使用类变量时,前面要有类名

    print(p1.x)               #也可以使用实例名,但是值都是一样的

    print(p2.x)               #因为类变量在内存中只有一份(类似全局变量),所以不管那个

    print(p3.x)               #实例变量去访问它,都是一个值

    运行结果;

    E:>python a.py

    3

    3

    3

    3

    8、实例化

     """
    类内存:
    存类的方法
    类变量
    """
     
    实例化:p2=Person("laoli")
    实例对象:p2
    实例方法:get_name
    实例变量:self.name
     
     参数通过构造函数传递到实例里面,做初始化设置使用
     需要往类中传值的时候,需要实现构造函数,构造函数的时候,self自动会被赋值
    class Person:
        def __init__(self,name):    #当需要向实例中传参数时,便需要写构造函数
            self.name = name

    p=Person("老王")
    print(p.name)
     
    9、继承
    1)
    让类进行一些扩展
     
     class Person:    #父类

        def __init__(self,name):
            self.name = name

        def set_name(self,name):    #父类中有set_name和get_name两个方法
            self.name = name

        def get_name(self):
            return self.name

    class AsianPerson(Person):    #子类,括号中写入父类名

        def __init__(self,name,nation):
            Person.__init__(self,name)
            self.name = name    #通过父类的构造方法的执行,可以生成一个self.name,此句可删
            self.nation = nation

        def set_nation(self,nation):
            self.nation = nation

        def get_nation(self):
            return self.nation

    ap= AsianPerson("laowang","china")    #实例化,写进两个参数
    print(ap.get_name())    #实例ap中类AsianPerson中并没有get_name()方法
    print(ap.get_nation())
    ap.set_name("laolaowang")    #实例ap中类AsianPerson中并没有set_name()方法
    print(ap.get_name())
        #但是执行结果均能够正常执行,说明了类的继承实现
     
    2) 同样的以上的代码中,也可以对父类进行实例化
    p=Person("老李")
    print(p.get_name())    #父类Person中,有get_name()方法;#运行正常
    print(p.get_nation())    #父类Person中,无get_nation()方法;#运行会报错
     

    3) 调用父类的构造方法:

            1) 如果代码中不写Person.__init__(self,name)

    class Person:

        def __init__(self,name):

            self.name = name

        def set_name(self,name):

            self.name=name

        def get_name(self):

            return self.name

    class AsianPerson(Person):

        def __init__(self,name,nation):

            self.nation=nation         #此处无父类的构造方法,所以未将name做初始化

                                    #所以想使用父类的self.name便失败了

        def set_nation(self,nation):

            self.nation=nation

        def get_nation(self):

            return self.nation

    ap=AsianPerson("laowang","China")

    print(ap.get_name())

    运行结果:

    E:>python a.py

    Traceback (most recent call last):

      File "a.py", line 25, in <module>

        print(ap.get_name())

      File "a.py", line 10, in get_name

        return self.name

    AttributeError: 'AsianPerson' object has no attribute 'name'

    会提示AsianPerson没有name属性

    综上:Person.__init__(self,name)的作用是:

    如果想使用父类中的方法和变量的话,则必须在子类的构造函数中,需要调用父类的构造方法,将父类的初始化数据传过去后,父类中的变量和实例方法全部可以被子类使用

    父类的私有变量与私有方法不会被继承,父类其他的公有变量和公有方法会被子类所继承

    4) 父类中有一个方法是修改自己所有属性的,那么子类调用父类方法就能修改父类的私有属性值:

    class Person:

        def __init__(self,name):

            self.__name = name

        def set_name(self,name):

            self.__name=name

        def get_name(self):

            return self.__name

    class AsianPerson(Person):

        def __init__(self,name,nation):

            Person.__init__(self,name)

            self.nation=nation

        def set_nation(self,nation):

            self.nation=nation

        def get_nation(self):

            return self.nation

    ap=AsianPerson("laowang","China")

    print(ap.get_name())         #子类调用父类中的私有变量

    print(ap.set_name("laoli"))    #子类修改父类中的私有变量

    print(ap.__name)            #在外部方访问私有变量

    运行结果:

    E:>python a.py

    laowang                

    None                      #子类可成功修改父类中的私有变量

    Traceback (most recent call last):

      File "a.py", line 28, in <module>

        print(ap.__name)

    AttributeError: 'AsianPerson' object has no attribute '__name'   #私有变量不可在外部访问

    5)如果父类中有私有变量,那么子类的方法是不能读取父类中的私有变量的

    class Person:

        def __init__(self):

            self.__name = "liuyujing"

        def set_name(self,name):

            self.__name=name

        def get_name(self):

            return self.__name

    class AsianPerson(Person):

        def __init__(self,name,nation):

            Person.__init__(self)

            self.nation=nation

        def get_name(self):

            return self.__name     #子类中的方法不能访问父类中的私有变量

    ap=AsianPerson("laowang","China")

    print(ap.get_name())

    运行结果:

    E:>python a.py

    Traceback (most recent call last):

      File "a.py", line 23, in <module>

        print(ap.get_name())

      File "a.py", line 20, in get_name

        return self.__name

    AttributeError: 'AsianPerson' object has no attribute '_AsianPerson__name'

     
    10、重写父类中的方法
     class Person:

        def __init__(self,name):
            self.name = name

        def set_name(self,name):
            self.name = name

        def get_name(self):
            return self.name

    class AsianPerson(Person):

        def __init__(self,name,nation):
            Person.__init__(self,name)      
            self.nation = nation

        def get_name(self):#重写了父类中的方法
            return "****:"+self.name

    ap= AsianPerson("laowang","china")
    print(ap.get_name())    #在调用时调用的是子类的get_name()方法,将父类的方法覆盖掉了
     

    子类中重写了父类的方法,如果使用父类创建实例对象时,调用的还是父类里的方法。

    重写:把父类的方法覆盖掉,使用子类的同名方法

    重载; 多个方法名一样,但是他们的参数类型,还有参数个数不一样(相对java说的),python不支持重载

    11、 明确调用父类中的方法

    调用父类的方法 
     super().get_name() 
     Person.get_name(self) 
     super(AsianPerson,self).get_name() 

    1) super().get_name()方式调用父类中的方法

    class Person:

        def __init__(self,name):

            self.name = name

        def set_name(self,name):

            self.name=name

        def get_name(self):

            return self.name

    class AsianPerson(Person):

        def __init__(self,names,nation):

            Person.__init__(self,name)

            self.nation=nation

        def set_nation(self,nation):

            self.nation=nation

        def get_nation(self):

            return self.nation

        def get_name(self):

            return "***:"+super().get_name()#调用父类中的get_name()方法,super是关键字

    ap=AsianPerson("laowang","China")

    print(ap.get_name())

    运行结果;

    E:>python a.py

    ***:laowang

    2) Person.get_name(self)方式调用父类中的方法

    class Person:

        def __init__(self,name):

            self.name = name

        def set_name(self,name):

            self.name=name

        def get_name(self):

            return self.name

    class AsianPerson(Person):

        def __init__(self,name,nation):

            Person.__init__(self,name)

            self.nation=nation

        def set_nation(self,nation):

            self.nation=nation

        def get_nation(self):

            return self.nation

        def get_name(self):

            return "***:"+Person.get_name(self)  #括号内需要写self

    ap=AsianPerson("laowang","China")

    print(ap.get_name())

    运行结果:

    E:>python a.py

    ***:laowang       

    3) super(AsianPerson,self).get_nam方式调用父类中的方法

    class Person:

        def __init__(self,name):

            self.name = name

        def set_name(self,name):

            self.name=name

        def get_name(self):

            return self.name

    class AsianPerson(Person):

        def __init__(self,name,nation):

            Person.__init__(self,name)

            self.nation=nation

        def set_nation(self,nation):

            self.nation=nation

        def get_nation(self):

            return self.nation

        def get_name(self):

            return "***:"+super(AsianPerson,self).get_name()

    ap=AsianPerson("laowang","China")

    print(ap.get_name())

    运行结果:

    E:>python a.py

    ***:laowang

     
  • 相关阅读:
    一、left
    padding溢出
    一、
    Python创建、删除桌面、启动组快捷方式的例子分享
    openstack常见问题解决方法总结
    __attribute__ 详解
    __ATTRIBUTE__ 知多少?
    CentOS如何设置终端显示字符界面区域的大小
    shell使用技巧
    openstack 安全策略权限控制等api接口
  • 原文地址:https://www.cnblogs.com/suitcases/p/10520167.html
Copyright © 2020-2023  润新知