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

时间:2022-12-16 17:40:44

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
        python入门(十三):面向对象(继承、重写、公有、私有)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
        python入门(十三):面向对象(继承、重写、公有、私有)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
        python入门(十三):面向对象(继承、重写、公有、私有)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):
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def get_name(self):#实例方法
        print(python入门(十三):面向对象(继承、重写、公有、私有)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):
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def get_name(self):#实例方法
        print(python入门(十三):面向对象(继承、重写、公有、私有)self.name)
    
    def get_name2(self):#实例方法
        print(python入门(十三):面向对象(继承、重写、公有、私有)self.name,python入门(十三):面向对象(继承、重写、公有、私有)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):    #构造函数只有在实例化的时候才会被执行
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name
        Person.x+=1

def get_name(self):#实例方法
        print(python入门(十三):面向对象(继承、重写、公有、私有)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
实例变量:python入门(十三):面向对象(继承、重写、公有、私有)self.name
 
 参数通过构造函数传递到实例里面,做初始化设置使用
 需要往类中传值的时候,需要实现构造函数,构造函数的时候,self自动会被赋值
class Person:
    def __init__(self,name):    #当需要向实例中传参数时,便需要写构造函数
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

p=Person("老王")
print(python入门(十三):面向对象(继承、重写、公有、私有)p.name)

 
9、继承
1)
让类进行一些扩展
 
 class Person:    #父类

def __init__(self,name):
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def set_name(self,name):    #父类中有set_name和get_name两个方法
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def get_name(self):
        return python入门(十三):面向对象(继承、重写、公有、私有)self.name

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

def __init__(self,name,nation):
        Person.__init__(self,name)
        python入门(十三):面向对象(继承、重写、公有、私有)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):
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def set_name(self,name):
        python入门(十三):面向对象(继承、重写、公有、私有)self.name = name

def get_name(self):
        return python入门(十三):面向对象(继承、重写、公有、私有)self.name

class AsianPerson(Person):

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

def get_name(self):#重写了父类中的方法
        return "****:"+python入门(十三):面向对象(继承、重写、公有、私有)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

 

python入门(十三):面向对象(继承、重写、公有、私有)的更多相关文章

  1. Python 入门 之 面向对象的三大特性(封装 &sol; 继承 &sol; 多态)

    Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态) 1.面向对象的三大特性: (1)继承 ​ 继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以 ...

  2. Python进阶&lpar;十三&rpar;----面向对象

    Python进阶(十三)----面向对象 一丶面向过程编程vs函数式编程vs面向对象编程 面向过程: ​ 简而言之,step by step 一步一步完成功能,就是分析出解决问题所需要的步骤,然后用函 ...

  3. Python入门篇-面向对象概述

    Python入门篇-面向对象概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.语言的分类 面向机器 抽象成机器指令,机器容易理解 代表:汇编语言 面向过程 做一件事情,排出个 ...

  4. Python入门之面向对象的&lowbar;&lowbar;init&lowbar;&lowbar;和&lowbar;&lowbar;new&lowbar;&lowbar;方法

    Python入门之面向对象的__init__和__new__方法

  5. 【学习笔记】--- 老男孩学Python,day18 面向对象------继承

    继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类, 父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 class Fathe ...

  6. Python入门之面向对象的多态和继承

    本章内容 Python面向对象的多态和继承对比 ========================================= 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的 ...

  7. Python入门之面向对象之类继承与派生

    本章内容 一.继承 二.抽象类 三.继承的实现原理 ======================================================= 一.继承 1. 继承的定义 继承是一 ...

  8. Python之路-面向对象&amp&semi;继承和多态&amp&semi;类属性和实例属性&amp&semi;类方法和静态方法

    一.面向对象 编程方式 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强…” 什么是面 ...

  9. Python入门之面向对象编程&lpar;四&rpar;Python描述器详解

    本文分为如下部分 引言——用@property批量使用的例子来引出描述器的功能 描述器的基本理论及简单实例 描述器的调用机制 描述器的细节 实例方法.静态方法和类方法的描述器原理 property装饰 ...

  10. Python入门-初始面向对象

    之前我们代码基本上都是面向过程的,今天我们就来初始一下python中一个重要的内容:面向对象 一.面向对象和面向过程(重点理解) 1.面向过程: 一切以事物的流程为核心. 核心是"过程&qu ...

随机推荐

  1. SQLite 的创建与编辑

    创建数据库语句 -(void)creatData { sqlite3 *sqlite = nil; NSString *filePath = [NSHomeDirectory() stringByAp ...

  2. ubunut 查看port被哪个程序占用

    查看8087port被哪个程序占用 lsof -i :8087 -n

  3. mybatis的学习笔记

    前几天学习了mybatis,今天来复习一下它的内容. mybatis是一个基于Java的持久层框架,那就涉及到数据库的操作.首先来提出第一个问题:java有jdbc连接数据库,我们为什么还要使用框架呢 ...

  4. yum install mariadb安装数据库开启不了

    centos7内置的MySQL镜像已经放弃Oracle公司的MySQL,改用MySQL的分支数据库mariaDB,使用以下安装mariadb: yum install mariadb 然后使用命令sy ...

  5. (16)JavaScript的流程控制&lpar;js的循环&rpar;

    流程控制有3种结构 1.顺序结构:代码执行的本质就是顺序结构 2.分支结构:if家族 语法规则: if (条件1) { //代码块1}else if (条件2){ //代码块1}//如果所有条件都不满 ...

  6. linux中ps命令

    ps的参数 -C的使用 [root@centos7 ~]# ps -C nginx -o user,pid,comm USER PID COMMAND root 2697 nginx nginx 26 ...

  7. 学习5&lowbar;STM32--外设通信方式

    就拿stm32的外设spi来说,通信方式主要有3种 > spi常规收发方式        (在轮询机制下通过判断缓冲区空与非空作为收发依据) > spi中断收发方式 (在中断机制下收发数据 ...

  8. 稀疏数据压缩查询方法:Rank &amp&semi; Select 操作

    1.稀疏数据的例子 对于网络图对应的节点关联矩阵.数据生成的哈希表等,这些存储起来是稀疏的,这样我们就会想到需要压缩空间.但是在压缩存储空间的同时,还要支持高效的查询操作. Rank & Se ...

  9. 从数据库中取出的数据,字段名为gb2312的 数据转码为utf8

    $pj = Pj::find()->where($map)->asArray()->one(); if(!empty($pj)) { foreach ($pj as $k=>$ ...

  10. 创建blob地址

    aa="121" "121" b=new Blob([aa]) Blob(3) {size: 3, type: ""} window.URL ...