精华内容
下载资源
问答
  • Python 3.7 Module Docs(64-bit) 点击之后,会出现一个网页(将我下载的Python3.7.4文件夹中包含的模块都了出来,页面不止这么点,还可以往下拉) IDLE(Python 3.7 64-bit) 一个Python编辑器,Python内置的集成...

    (还在更新中…) 这篇博客花费了我的大量时间和精力,从创作到维护;若认可本篇博客,希望给一个点赞、收藏

    并且,遇到了什么问题,请在评论区留言,我会及时回复的


    这本书对Python的知识点的描述很详细,而且排版看的很舒服

    1. 几个例题: 假装自己从零开始学,将一些有代表性、有意思的例题抽取出来
    2. 部分复习题: 遇到有意思的复习题,我会拿出来,并且进行分析
    3. 上机实践: 全部上机实践题的解题思路

    文章目录

    第一章 Python概述


    几个例题

    一:Python3.7.4下载

    python3.7.4下载地址:https://www.python.org/downloads/release/python-374/
    页面最下面:

    下载,安装完python后:出现的四个玩意:Python 3.7 Module Docs,IDLE,Python 3.7 Manuals,Python 3.7(64-bit)

    1. Python 3.7 Module Docs(64-bit)
      点击之后,会出现一个网页(将我下载的Python3.7.4文件夹中包含的模块都列了出来,页面不止这么点,还可以往下拉)

    2. IDLE(Python 3.7 64-bit)
      一个Python编辑器,Python内置的集成开发工具

    3. Python 3.7 Manuals(64-bit)
      Python 3.7 开发手册

    4. Python 3.7(64-bit)
      控制台中运行Python

    二:更新pip和setuptools包,安装NumPy包,安装Matplotlib包

    以下三个命令都是在控制台(windows中的cmd)中运行

    更新pip和setuptools包

    1. pip用于安装和管理Python扩展包
    2. setuptools用于发布Python包
    python -m pip install -U pip setuptools
    

    安装NumPy

    Python扩展模块NumPy提供了数组和矩阵处理,以及傅立叶变换等高效的数值处理功能

     python -m pip install NumPy
    

    安装Matplotlib包

    Matplotlib是Python最著名的绘图库之一,提供了一整套和MATLAB相似的命令API,既适合交互式地进行制图,也可以作为绘图控件方便地嵌入到GUI应用程序中

    python -m pip install Matplotlib
    

    三:使用IDLE打开和执行Python源文件程序

    首先:
    有一个.py文件test.py
    在这里插入图片描述

    使用IDLE打开.py文件的两种方式:

    1. 右键test.py---->Edit With IDLE---->Edit With IDLE 3.7(64-bit)
    2. 打开IDLE,然后File---->Open(或者ctrl+O)选择.py文件

    运行

    Run---->Run Module(或者F5
    就会出现这个界面,执行结果显示在这个界面中

    补充一点:
    如果在IDLE中编辑.py文件,记得修改后要保存(ctrl+s),再运行(F5

    四:使用资源管理器运行hello.py

    hello.py文件在桌面

    import random
    
    print("hello,Python")
    print("你今天的随机数字是:",random.choice(range(10)))#输出在0-9之间随机选择的整数
    input()
    
    1. 在桌面打开PowerShell(还有两种输入方式:python hello.py或者.\hello.py
    2. 或者在桌面打开cmd, 就输入hello.py或者python hello.py

    补充:上述两种命令中的hello.py都是相对路径,因为文件在桌面,而且我是在桌面打开cmd,所以文件路劲可以这么简简单单的写。如果文件存储位置和cmd打开位置不一样,请使用绝对路径

    五:命令行参数示例hello_argv.py

    hello_argv.py文件在桌面

    import sys
    
    print("Hello,",sys.argv[1])
    #这样写也行:
    #print("Hello,"+sys.argv[1])
    
    1. 在桌面打开PowerShell(还有两种输入方式:python hello_argv.py 任意输入或者./hello_argv.py 任意输入
    2. 或者在桌面打开cmd,就输入hello_argv.py 任意输入或者python hello_argv.py 任意输入

    补充:以图中第一个命令举例,hello_argv.pysys.argv[0]Pythonsys.argv[1]

    第二章 Python语言基础


    选择题:1、3、7、8

    1. 在Python中,以下标识符合法的是

    A. _B. 3CC. it’sB. str

    答案:A

    1. 标识符的第一个字符必须是字母,下划线(_);其后的字符可以是字母、下划线或数字。
    2. 一些特殊的名称,作为python语言的保留关键字,不能作为标识符
    3. 以双下划线开始和结束的名称通常具有特殊的含义。例如__init__为类的构造函数,一般应避免使用

    B:以数字开头,错误
    C:使用了',不是字母、下划线或数字
    D:str是保留关键字

    3. 在下列Python语句中非法的是

    A. x = y =1B. x = (y =1)C. x,y = y,xB. x=1;y=1

    答案:B,C

    7. 为了给整型变量x,y,z赋初值10,下面Python赋值语句正确的是

    A. xyz=10B. x=10 y=10 z=10C. x=y=z=10B. x=10,y=10,z=10

    答案:C

    1. 分号;用于在一行书写多个语句
    2. python支持链式赋值

    A:赋值对象是xyz
    B:分号;用于在一行书写多个语句,而不是' '(即空格)
    D:分号;用于在一行书写多个语句,而不是,

    8. 为了给整型变量x,y,z赋初值5,下面Python赋值语句正确的是

    A. x=5;y=5;z=5B. xyz=5C. x,y,z=10B. x=10,y=10,z=10

    答案:A

    Pytho能支持序列解包赋值,但是变量的个数必须与序列的元素个数一致,否则会报错

    B:赋值对象是xyz
    C:序列解包赋值,变量的个数必须与序列的元素个数一致,否则会报错
    D:分号;用于在一行书写多个语句,而不是,

    思考题:9

    9.下列Python语句的输出结果是

    def f():pass
    print(type(f()))
    

    结果:<class 'NoneType'>

    NoneType数据类型包含唯一值None,主要用于表示空值,如没有返回值的函数的结果

    上机实践:2~6

    2. 编写程序,输入本金、年利率和年数,计算复利(结果保留两位小数)

    money = int(input("请输入本金:"))
    rate = float(input("请输入年利率:"))
    years = int(input("请输入年数:"))
    amount = money*((1+rate/100)**years)
    print(str.format("本金利率和为:{0:2.2f}",amount))
    

    运行:

    请输入本金:1000
    请输入年利率:6.6
    请输入年数:10
    本金利率和为:1894.84
    

    3. 编写程序,输入球的半径,计算球的表面积和体积(结果保留两位小数)

    import math
    r = float(input("请输入球的半径:"))
    area = 4 * math.pi * r**2
    volume = 4/3*math.pi*r**3
    print(str.format("球的表面积为:{0:2.2f},体积为:{1:2.2f}",area,volume))
    

    运行:

    请输入球的半径:666
    球的表面积为:5573889.08,体积为:1237403376.70
    

    4. 编写程序,声明函数getValue(b,r,n),根据本金b,年利率r和年数n计算最终收益v

    money = int(input("请输入本金:"))
    rate = float(input("请输入年利率(<1):"))
    years = int(input("请输入年数:"))
    
    def getValue(b,r,n):
        return b*(1+r)**n
    
    print(str.format("本金利率和为:{0:2.2f}",getValue(money,rate,years)))
    

    运行:

    请输入本金:10000
    请输入年利率(<1):0.6
    请输入年数:6
    本金利率和为:167772.16
    

    5. 编写程序,求解一元二次方程x2-10x+16=0

    from math import sqrt 
    x = (10+sqrt(10*10-4*16))/2
    y = (10-sqrt(10*10-4*16))/2
    print(str.format("x*x-10*x+16=0的解为:{0:2.2f},{1:2.2f}",x,y))
    

    运行:

    x*x-10*x+16=0的解为:8.00,2.00
    

    6. 编写程序,提示输入姓名和出生年份,输出姓名和年龄

    import datetime
    sName = str(input("请输入您的姓名:"))
    birthday = int(input("请输入您的出生年份:"))
    age = datetime.date.today().year - birthday
    print("您好!{0}。您{1}岁。".format(sName,age))
    

    运行:

    请输入您的姓名:zgh
    请输入您的出生年份:1999
    您好!zgh。您20岁。
    

    案例研究:使用Pillow库处理图像文件

    https://blog.csdn.net/Zhangguohao666/article/details/102060722

    通过此案例,进一步了解Python的基本概念:模块、对象、方法和函数的使用

    第三章 程序流程控制


    几个例题

    一:编程判断某一年是否为闰年

    闰年:年份能被4整除但不能被100整除,或者可以被400整除。
    口诀:四年一闰,百年不闰,四百必闰

    代码一:

    y = int(input("请输入要判断的年份:"))
    if((y % 4 == 0 and y % 100 != 0) or y % 400 == 0):
        print("是闰年")
    else:
        print("不是闰年")
    

    代码二(使用calendar模块的isleap()函数来判断):

    from calendar import isleap
    
    y = int(input("请输入要判断的年份:"))
    if(isleap(y)):print("闰年")
    else:print("不是闰年")
    

    二:利用嵌套循环打印九九乘法表

    九九乘法表:

    for i in range(1,10):
        s = ""
        for j in range(1,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    下三角:

    for i in range(1,10):
        s = ""
        for j in range(1,i+1):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    上三角:

    for i in range(1,10):
        s = ""
        for k in range(1,i):
            s += "                   "
        for j in range(i,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    三:enumerate()函数和下标元素循环示例

    Python语言中的for循环直接迭代对象集合中的元素,如果需要在循环中使用索引下标访问集合元素,则可以使用内置的enumerate()函数

    enumerate()函数用于将一个可遍历的数据对象(例如列表、元组或字符串)组合为一个索引序列,并返回一个可迭代对象,故在for循环当中可直接迭代下标和元素

    seasons = ["Spring","Summer","Autumn","Winter"]
    for i,s in enumerate(seasons,start=1):    #start默认从0开始
        print("第{0}个季节:{1}".format(i,s))
    

    运行:

    第1个季节:Spring
    第2个季节:Summer
    第3个季节:Autumn
    第4个季节:Winter
    

    四:zip()函数和并行循环示例

    如果需要并行遍历多个可迭代对象,则可以使用Python的内置函数zip()

    zip()函数将多个可迭代对象中对应的元素打包成一个个元组,然后返回一个可迭代对象。如果元素的个数不一致,则返回列表的长度与最短的对象相同。

    利用运算符*还可以实现将元组解压为列表

    evens = [0,2,4,6,8]
    odds = [1,3,5,7,9]
    for e,o in zip(evens,odds):
        print("{0} * {1} = {2}".format(e,o,e*o))
    

    运行:

    0 * 1 = 0
    2 * 3 = 6
    4 * 5 = 20
    6 * 7 = 42
    8 * 9 = 72
    

    五:map()函数和循环示例

    如果需要遍历可迭代对象,并使用指定函数处理对应的元素,则可以使用Python的内置函数map()

    map(func,seq1[,seq2,...])
    
    • func作用于seq中的每一个元素,并将所有的调用结果作为可迭代对象返回。
    • 如果func为None,该函数的作用等同于zip()函数

    计算绝对值:

    >>> list(map(abs, [-1, 0, 7, -8]))
    [1, 0, 7, 8]
    

    计算乘幂:

    >>> list(map(pow, range(5), range(5)))
    [1, 1, 4, 27, 256]
    

    计算ASCII码:

    >>> list(map(ord, 'zgh'))
    [122, 103, 104]
    

    字符串拼接(使用了匿名函数lambda):

    >>> list(map(lambda x, y: x+y, 'zgh', '666'))
    ['z6', 'g6', 'h6']
    

    选择题:1、2、3

    1. 下面的Python循环体的执行次数与其他不同的是

    A.

    i = 0						
    while(i <= 10):
    	print(i)
    	i = i + 1
    

    B.

    i = 10
    while(i > 0):
    	print(i)
    	i = i - 1
    

    C.

    for i in range(10):
    	print(i)
    

    D.

    for i in range(10,0,-1):
    	print(i)
    

    答案:A

    A:[0,10] 执行11次
    B:[10,1] 执行10次
    C:[0,9) 执行10次
    D:[10,0) 执行10次

    2. 执行下列Python语句将产生的结果是

    x = 2; y = 2.0
    if(x == y): print("Equal")
    else: print("Not Equal")
    
    A. EqualB. Not EqualC. 编译错误D. 运行时错误

    答案:A

    Python中的自动类型转换:

    1. 自动类型转换注意针对Number数据类型来说的
    2. 当2个不同类型的数据进行运算的时候,默认向更高精度转换
    3. 数据类型精度从低到高:bool int float complex
    4. 关于bool类型的两个值:True 转化成整型是1;False 转化成整型是0

    int类型的2转化为float类型的2.0

    3. 执行下列Python语句将产生的结果是

    i= 1 	
    if(i): print(True) 	
    else: print(False)
    
    A. 输出1B. 输出TrueC. 输出FalseD. 编译错误

    答案:B

    在Python中,条件表达式最后被评价为bool值True或False。

    如果表达式的结果为数值类型(0),空字符串(""),空元组(()),空列表([]),空字典({}),其bool值为False,否则其bool值为True

    填空题:6

    6. 要使语句for i in range(_,-4,-2)循环执行15次,则循环变量i的初值应当为

    答案:26或者25

    一开始我给的答案是26,经过评论区 的提醒:
    在这里插入图片描述

    >>> a = 0
    >>> for i in range(26, -4, -2): a+=1
    
    >>> print(a)
    15
    
    >>> a = 0
    >>> for i in range(25, -4, -2): a+=1
    
    >>> print(a)
    15
    

    这种题目有一个规律:for i in range(x,y,z):
    若循环中没有break或者continue语句,
    执行次数的绝对值:result = (x-y)÷z

    但实际上没有这么简单:

    • 如果步长为 -1或者1,那么答案只有一个
    • 如果步长为 -2或者2,那么答案有两个
    • 如果步长为 -3或者3,那么答案有三个

    通过公式算出 x 之后,

    • 如果步长为2,还要计算 (x ± 1) - z × (result-1) 的值,然后再经过琐碎的判断即可
    • 如果步长为3,还要计算 (x ± 2) - z × (result-1) 的值,…

    虽然看着麻烦,但实际上是很好理解的

    思考题:3~6

    3. 阅读下面的Python程序,请问程序的功能是什么?

    from math import sqrt
    
    n = 0
    for m in range(101,201,2):
        k = int(sqrt(m))
        for i in range(2, k+2):
            if m % i == 0:break
        if i == k + 1:
            if n % 10 == 0:print()
            print('%d' % m,end = " ")
            n += 1
    

    输出101到200之间的素数
    每行输出10个,多余换行

    运行:

    101 103 107 109 113 127 131 137 139 149 
    151 157 163 167 173 179 181 191 193 197 
    199
    

    素数(质数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

    4. 阅读下面的Python程序,请问输出的结果使什么?

    n = int(input("请输入图形的行数:"))
    for i in range(0, n):
        for j in range(0, 10 - i):print(" ", end=" ")
        for k in range(0, 2 * i + 1):print(" * ", end=" ")
        print("\n")
    

    输出的是一个金字塔

    运行:

    请输入图形的行数:4
                         *  
    
                       *   *   *  
    
                     *   *   *   *   *  
    
                   *   *   *   *   *   *   *  
    

    5. 阅读下面的Python程序,请问输出的结果使什么?程序的功能是什么?

    for i in range(100,1000):
        n1 = i // 100
        n2 = i // 10 % 10
        n3 = i % 10
        if(pow(n1, 3) + pow(n2, 3) + pow(n3, 3) == i):print(i, end=" ")
    

    输出三位数中所有的水仙花数

    运行:

    153 370 371 407 
    

    水仙花数 是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身

    6. 阅读下面的Python程序,请问输出的结果使什么?程序的功能是什么?

    for n in range(1,1001):
        total = 0; factors = []
        for i in range(1, n):
            if(n % i == 0):
                factors.append(i)
                total += i
        if(total == n):print("{0} : {1}".format(n, factors))    
    

    输出1到1000的所有完数,并输出每个完数的所有因子

    运行:

    6 : [1, 2, 3]
    28 : [1, 2, 4, 7, 14]
    496 : [1, 2, 4, 8, 16, 31, 62, 124, 248]
    

    完数 所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身

    上机实践:2~14

    2. 编写程序,计算1=2+3+…+100之和

    1. 使用for循环(递增):
    total = 0
    for i in range(101):
        total += i
    print(total) 
    
    1. 使用求和公式:
    >>> (1 + 100) * 100 /2
    5050.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1, 101)))[99]
    5050
    

    3. 编写程序,计算10+9+8+…+1之和

    1. 使用for循环(递增):
    total = 0
    for i in range(11):
        total += i
    print(total) 
    
    1. 使用for循环(递减):
    total = 0
    for i in range(10,0,-1):
        total += i
    print(total)   
    
    1. 使用求和公式:
    >>> (1 + 10) * 10 / 2
    55.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1,11)))[9]
    55
    

    4. 编写程序,计算1+3+5+7+…+99之和

    1. 使用for循环(递增):
    total = 0
    for i in range(1,100,2):
        total += i
    print(total)     
    
    1. 使用求和公式:
    >>> (1 + 99) * 50 /2
    2500.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> list(itertools.accumulate(range(1,100,2)))[49]
    2500
    

    5. 编写程序,计算2+4+6+8+…+100之和

    1. 使用for循环(递增):
    total = 0
    for i in range(2,101,2):
        total += i
    print(total)     
    
    1. 使用求和公式:
    >>> (2 + 100) * 50 / 2
    2550.0
    
    1. 使用累计迭代器itertools.accumulate
    >>> import itertools
    >>> x = list(itertools.accumulate(range(2,101,2)))
    >>> x[len(x)-1]
    2550
    

    6. 编写程序,使用不同的实现方法输出2000~3000的所有闰年

    代码一:

    for y in range(2000,3001):
        if((y % 4 == 0 and y % 100 != 0) or y % 400 == 0):
            print(y,end = ' ')
    

    代码二(使用calendar模块的isleap()函数来判断):

    from calendar import isleap
    
    for y in range(2000,3001):
        if(isleap(y)):print(y,end = " ")
    

    运行:

    2000 2004 2008 2012 2016 2020 2024 2028 2032 2036 2040 2044 2048 2052 2056 2060 2064 2068 2072 2076 2080 2084 2088 2092 2096 2104 2108 2112 2116 2120 2124 2128 2132 2136 2140 2144 2148 2152 2156 2160 2164 2168 2172 2176 2180 2184 2188 2192 2196 2204 2208 2212 2216 2220 2224 2228 2232 2236 2240 2244 2248 2252 2256 2260 2264 2268 2272 2276 2280 2284 2288 2292 2296 2304 2308 2312 2316 2320 2324 2328 2332 2336 2340 2344 2348 2352 2356 2360 2364 2368 2372 2376 2380 2384 2388 2392 2396 2400 2404 2408 2412 2416 2420 2424 2428 2432 2436 2440 2444 2448 2452 2456 2460 2464 2468 2472 2476 2480 2484 2488 2492 2496 2504 2508 2512 2516 2520 2524 2528 2532 2536 2540 2544 2548 2552 2556 2560 2564 2568 2572 2576 2580 2584 2588 2592 2596 2604 2608 2612 2616 2620 2624 2628 2632 2636 2640 2644 2648 2652 2656 2660 2664 2668 2672 2676 2680 2684 2688 2692 2696 2704 2708 2712 2716 2720 2724 2728 2732 2736 2740 2744 2748 2752 2756 2760 2764 2768 2772 2776 2780 2784 2788 2792 2796 2800 2804 2808 2812 2816 2820 2824 2828 2832 2836 2840 2844 2848 2852 2856 2860 2864 2868 2872 2876 2880 2884 2888 2892 2896 2904 2908 2912 2916 2920 2924 2928 2932 2936 2940 2944 2948 2952 2956 2960 2964 2968 2972 2976 2980 2984 2988 2992 2996 
    

    7. 编写程序,计算Sn=1-3+5-7+9-11…

    代码一:

    n = int(input("项数:"))
    total = 0
    flag = True
    for i in range(1,2*n,2):
        if(flag):
            total += i
            flag = False
        else:
            total -= i
            flag = True
    print(total)
    

    代码二:

    n = int(input("项数:"))
    total = 0
    x = 2
    for i in range(1,2*n,2):
        total += pow(-1,x)*i
        x += 1 
    print(total)
    

    运行:

    项数:10
    -10
    

    8. 编写程序,计算Sn=1+1/2+1/3+…

    n = int(input("项数:"))
    total = 0.0
    for i in range(1,n+1):
        total += 1/i 
    print(total)
    

    运行:

    项数:10
    2.9289682539682538
    

    9. 编写程序,打印九九乘法表。要求输入九九乘法表的各种显示效果(上三角,下三角,矩形块等方式)

    矩形块:

    for i in range(1,10):
        s = ""
        for j in range(1,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    下三角:

    for i in range(1,10):
        s = ""
        for j in range(1,i+1):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    上三角:

    for i in range(1,10):
        s = ""
        for k in range(1,i):
            s += "                   "
        for j in range(i,10):
            s += str.format("%d * %d = %02d  " %(i, j, i*j))
        print(s)
    

    10. 编写程序,输入三角形的三条边,先判断是否可以构成三角形,如果可以,则进一步求三角形的周长和面积,否则报错“无法构成三角形!”

    from math import sqrt
    
    a = float(input("请输入三角形的边长a:"))
    b = float(input("请输入三角形的边长b:"))
    c = float(input("请输入三角形的边长c:"))
    
    if(a < b): a,b = b,a
    if(a < c): a,c = c,a
    if(b < c): b,c = c,b
    
    if(a < 0 or b < 0 or c < 0 or b+c <= a): print("无法构成三角形!")
    else:
        h = (a+b+c)/2
        area = sqrt(h*(h-a)*(h-b)*(h-c))
        print("周长:{0},面积:{1}".format(a+b+c,area))
    

    运行:

    请输入三角形的边长a:4
    请输入三角形的边长b:3
    请输入三角形的边长c:5
    周长:12.0,面积:6.0
    

    11. 编写程序,输入x,根据如下公式计算分段函数y的值。请分别用单分支语句,双分支语句结构以及条件运算语句等方法实现

    y = (x2-3x)/(x+1) + 2π + sinx (x≥0 )
    y = ln(-5x) + 6√(|x|+e4) - (x+1)3 (x<0)

    单分支语句:

    import math
    
    x = float(input("请输入x:"))
    if(x >= 0):
        y = (x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)
    if(x < 0):
        y = math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)
    
    print(y)
    
    
    

    双分支语句:

    import math
    
    x = float(input("请输入x:"))
    if(x >= 0):
        y = (x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)
    else:
        y = math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)
    
    print(y)
    

    条件运算语句:

    import math
    
    x = float(input("请输入x:"))
    y = ((x*x - 3*x)/(x+1) + 2*math.pi + math.sin(x)) if(x >= 0) \
    else (math.log(-5*x) + 6 * math.sqrt(abs(x) + math.exp(4)) - pow(x+1,3)) 
    
    print(y)
    

    运行一:

    请输入x:666
    668.2715406628656
    

    运行二:

    请输入x:-666
    294079794.1744833
    

    12. 编写程序,输入一元二次方程的3个系数a、b、c,求ax2+bx+c=0方程的解

    import math
    
    a = float(input("请输入系数a:"))
    b = float(input("请输入系数b:"))
    c = float(input("请输入系数c:"))
    
    delta = b*b -4*a*c
    
    if(a == 0):
        if(b == 0): print("无解")
        else: print("有一个实根:",-1*c/b)
    elif(delta == 0): print("有两个相等实根:x1 = x2 = ", (-1*b)/(2*a))
    elif(delta > 0): print("有两个不等实根:x1 = {0},x2 = {1}".format\
                           ((-1*b +math.sqrt(delta))/2*a,(-1*b -math.sqrt(delta))/2*a))
    elif(delta < 0): print("有两个共轭复根:x1 = {0},x2 = {1}".format\
                           (complex( (-1*b)/(2*a),math.sqrt(delta*-1)/(2*a)),complex( (-1*b)/(2*a),-1*math.sqrt(delta*-1)/(2*a))))
    

    运行一:

    请输入系数a:0
    请输入系数b:0
    请输入系数c:10
    无解
    

    运行二:

    请输入系数a:0
    请输入系数b:10
    请输入系数c:5
    有一个实根: -0.5
    

    运行三:

    请输入系数a:1
    请输入系数b:8
    请输入系数c:16
    有两个相等实根:x1 = x2 =  -4.0
    

    运行四:

    请输入系数a:1
    请输入系数b:-5
    请输入系数c:6
    有两个不等实根:x1 = 3.0,x2 = 2.0
    

    运行五:

    请输入系数a:5
    请输入系数b:2
    请输入系数c:1
    有两个共轭复根:x1 = (-0.2+0.4j),x2 = (-0.2-0.4j)
    

    13. 编写程序,输入整数n(n≥0),分别利用for循环和while循环求n!

    1. for循环
    n = int(input("请输入n:"))
    
    if(n == 0): total = 1
    if(n > 0):
        total = 1
        for i in range(n,0,-1):
            total *= i
    
    print(total)
    
    
    1. while循环
    n = int(input("请输入n:"))
    
    if(n == 0): total = 1
    if(n > 0):
        total = 1
        while(n >= 1):
            total *= n
            n -= 1
    
    print(total)
    
    1. 补充一个:使用累计迭代器itertools.accumulate
    >>> import itertools, operator
    >>> n = int(input('请输入n:'))
    请输入n:7
    >>> x = list(accumulate(range(1, n+1), operator.mul))
    >>> x[len(x)-1]
    5040
    

    14. 编写程序,产生两个0~100(包含0和100)的随机整数a和b,求这两个整数的最大公约数和最小公倍数

    1. 现有知识点解决方法
    
    import random
    
    a = random.randint(0,100)
    b = random.randint(0,100)
    sum = a*b
    
    print(a) #输出原来的a,b
    print(b)
    
    if(a < b): a,b = b,a
    
    while(a%b != 0):
        a,b = b,a%b
    
    print("最大公约数:{0},最小公倍数:{1}".format(b,sum/b))
    
    
    1. 补充:使用生成器(generate)函数:yield
    >>> def func(a, b):
    	if(a < b): a,b = b,a
    	while(a%b != 0):
    		a,b = b,a%b
    		yield b
    
    		
    >>> import random
    >>> if __name__ == '__main__':
    	a = random.randint(0,100)
    	b = random.randint(0,100)
    	sum = a*b
    	print(a,b)
    	t = list(iter(func(a, b)))
    	gcd = t[len(t)-1]
    	print("gcd = {0}, mcm = {1}".format(gcd, sum/gcd))
    
    	
    29 65
    gcd = 1, mcm = 1885.0
    
    1. 补充:使用math模块中的gcd(x,y)函数
    >>> import random
    >>> import math
    >>> if __name__ == '__main__':
    	a = random.randint(0,100)
    	b = random.randint(0,100)
    	sum = a*b
    	print(a,b)
    	gcd = math.gcd(a,b)
    	print("gcd = {0}, mcm = {1}".format(gcd, sum/gcd))
    
    	
    29 48
    gcd = 1, mcm = 1392.0
    

    案例研究:使用嵌套循环实现图像处理算法

    https://blog.csdn.net/Zhangguohao666/article/details/103935185

    通过图像处理算法案例,深入了解Python数据结构和基本算法流程

    第四章 常用内置数据类型


    几个例题

    一:Python内置数据类型概述

    Python中一切皆为对象,而每个对象属于某个数据类型

    Python的数据类型包括:

    1. 内置的数据类型
    2. 模块中定义的数据类型
    3. 用户自定义的类型

    四种内置的数值类型:int,float,bool,complex

    1. int
      与其他计算机语言有精度限制不同,Python中的整数位数可以为任意长度(只受限于计算机内存)。
      整型对象是不可变对象。
    2. float
      与其他计算机语言中的double和float对应
      Python的浮点类型的精度和系统相关
    3. bool
    4. complex
      当数值字符串中包含虚部j(或J)时即复数字面量

    序列数据类型:str,tuple,bytes,list,bytearray

    序列数据类型表示若干有序数据.

    不可变序列数据类型:

    1. str(字符串)
      表示Unicode字符序列,例如:“zgh666”
      在Python中没有独立的字符数据类型,字符即长度为1的字符串
    2. tuple(元组)
      表示任意数据类型的序列,例如:(“z”,“g”,“h”,6,6,6)
    3. bytes(字节序列)
      表示字节(8位)序列数据

    可变序列数据类型:

    1. list(列表)
      表示可以修改的任意类型数据的序列,比如:[‘z’,‘g’,‘h’,6,6,6]
    2. bytearray(字节数组)
      表示可以修改的字节(8位)数组

    集合数据类型:set,frozenset

    集合数据类型表示若干数据的集合,数据项目没有顺序,且不重复

    1. set(集)
      例如:{1,2,3}
    2. frozenset(不可变集)

    字典数据类型:dict

    字典数据类型用于表示键值对的字典
    例如:{1:"zgh", 2:666}

    NoneType,NotImplementedType,EllipsisType

    1. NoneType数据类型包含唯一值None,主要用于表示空值,如没有返回值的函数的结果
    2. NotImplementedType数据类型包含唯一值NotImplemented,在进行数值运算和比较运算时,如果对象不支持,则可能返回该值
    3. EllipsisType数据类型包含唯一值Ellipsis,表示省略字符串符号...

    其他数据类型

    Python中一切对象都有一个数据类型,模块、类、对象、函数都属于某种数据类型
    Python解释器包含内置类型,
    例如:
    代码对象Code objects
    框架对象Frame objects
    跟踪对象Traceback objects
    切片对象Slice objects
    静态方法对象Static method objects
    类方法对象Class method objects

    二:整型字面量示例

    Python3.7支持使用下划线作为整数或者浮点数的千分位标记,以增强大数值的可阅读性。
    二进制、八进制、十六进制则使用下划线区分4位标记

    1_000_000_000  #输出1000000000
    
    0xff_ff_ff_ff  #输出4294967295
    0x_FF_FF_FF_FF  #输出4294967295
    

    三:字符串字面量示例

    两个紧邻的字符串,如果中间只有空格分隔,则自动拼接位一个字符串

    'zgh' '666'  #输出'zgh666'
    'zgh' + "666"   #输出'zgh666'
    

    四:转义字符示例

    转义字符后跟Unicode编码也可以表示字符

    1. \ooo八进制Unicode码对应的字符
    2. \xhh十六进制Unicode码对应的字符
    '\101'  #输出'A'
    '\x41'  #输出'A'
    

    使用r’‘或者R’'的字符串称为原始字符串,其中包含的任何字符都不进行转义

    s = r'换\t行\t符\n'
    s  		  #输出:'换\\t行\\t符\\n'
    print(s)  #输出:换\\t行\\t符\\n
    

    五:字符串的格式化

    一:

    "student number:{0},score_average:{1}".format(2,100)
    #输出:'student number:2,score_average:100'
    

    二:

    str.format("student number:{0},score_average:{1}",2,100)
    #输出:'student number:2,score_average:100'
    

    三(兼容Python2的格式,不推荐使用):

     "student number:%4d,score_average:%2.1f" %(2,100)
     #输出:'student number:   2,score_average:100.0'
    

    六:字符串示例,格式化输出字符串堆积的三角形

    1. str.center()方法用于字符串两边填充
    2. str.rjust()方法用于字符串右填充
    print("1".center(20))		#一行20个字符,居中对齐
    print(format("121","^20"))	#一行20个字符,居中对齐
    print("1".rjust(20,"*"))	#一行20个字符,右对齐,加*
    print(format("121","*>20"))	#一行20个字符,右对齐,加*
    

    运行:

             1          
            121         
    *******************1
    *****************121
    

    选择题:11

    11. 关于Python字符串,下列说法错误的是

    A. 字符即长度为1的字符串
    B. 字符串以/0标识字符串的结束
    C. 用户既可以用单引号,也可以用双引号创建字符串
    D. 用三引号字符串中可以包含换行回车等特殊字符

    答案:B

    Python中字符串不是用\0来判断字符串结尾,
    每个字符串都存有字符串的长度,通过计数来判断是否到达结尾。

    虽然在c语言中\0就是来判断字符串的结尾;

    填空题:4、7、8、9、10、13、21

    4. Python表达式3 ** 2 ** 3的值为

    答案:6561

    表达式中,相同优先级的运算,从右往左

    7. Python语句print(pow(-3,2),round(18.67,1),round(18.67,-1))的输出结果是

    答案:9 18.7 20.0

    pow()幂运算
    round()四舍六入,五留双

    8. Python语句print(round(123.84,0),round(123.84,-2),floor(15.5))的输出结果是

    答案:124.0 100.0 15

    补充:floor()是math模块中的方法,向下取整

    9. Python语句print(int(‘20’,16),int(‘101’,2))的输出结果是

    答案:32 5

    注意:int(x,y)是指将y进制的数值x转化为10进制数

    10. Python语句print(hex(16),bin(10))的输出结果是

    答案:0x10 0b1010

    hex(x)将十进制数x转化为十六进制,以字符串形式输出
    bin(x)将十进制数x转化为二进制,以字符串形式输出

    13. Python语句print(gcd(12,16),divmod(7,3))的输出结果是

    答案:4 (2,1)

    gcd()是math模块中的函数,求最大公约数
    divmod()是内置函数,返回商和余数

    21. Python语句序列 x=True;y=False;z=False;print(x or y and z) 的运行结果是

    答案:True

    and优先级比or高

    思考题:5

    5. 阅读下面的Python程序,请问输出结果是什么?

    from decimal import *
    
    ctx = getcontext()
    ctx.prec = 2
    print(Decimal('1.78'))#1.78
    print(Decimal('1.78') + 0)#1.8
    ctx.rounding = ROUND_UP
    print(Decimal('1.65') + 0)#1.7
    print(Decimal('1.62') + 0)#1.7
    print(Decimal('-1.45') + 0)#-1.5
    print(Decimal('-1.42') + 0)#-1.5
    ctx.rounding = ROUND_HALF_UP
    print(Decimal('1.65') + 0)#1.7
    print(Decimal('1.62') + 0)#1.6
    print(Decimal('-1.45') + 0)#-1.5
    ctx.rounding = ROUND_HALF_DOWN
    print(Decimal('1.65') + 0)#1.6
    print(Decimal('-1.45') + 0)#-1.4
    

    上机实践:2~14

    2. 编写程序,格式化输出杨辉三角

    杨辉三角即二项式定理的系数表,各元素满足如下条件:第一列及对角线上的元素均为1;其余每个元素等于它上一行同一列元素与前一列元素之和

    我使用了一个更加精妙的规律
    比如第一行为1
    第二行:01 + 10 = 11
    第三行:011 + 110 = 121
    第四行:0121 + 1210 = 1331
    。。。

    def generate(numRows):
        l1 = [1]
        n = 0
        while n < numRows:
            print(str(l1).center(66))
            l1 = [sum(t) for t in zip([0] + l1, l1 + [0])]  #利用zip函数算出每一行 如第二行 zip([0,1],[1,0])=[1,1],以此类推
            n += 1
    a=int(input("请输入行数"))
    generate(a)
    

    运行:

    请输入行数4
                                   [1]                                
                                  [1, 1]                              
                                [1, 2, 1]                             
                               [1, 3, 3, 1]  
    

    3. 输入直角三角形的两个直角边,求三角形的周长和面积,以及两个锐角的度数。结果保留一位小数

    import math
    
    a = float(input("请输入直角三角形的直角边a:"))
    b = float(input("请输入直角三角形的直角边b:"))
    c = math.sqrt(a*a+b*b)
    
    p = a + b + c
    area = 0.5*a*b
    print("三角形的周长:{0:1.1f},面积:{1:1.1f}".format(p,area))
    
    sina = a/c
    sinb = b/c
    
    a_degree = round(math.asin(sina) * 180 / math.pi,0)
    b_degree = round(math.asin(sinb) * 180 / math.pi,0)
    
    print("三角形直角边a的度数:{0},b的度数:{1}".format(a_degree,b_degree))
    

    运行:

    请输入直角三角形的直角边a:3
    请输入直角三角形的直角边b:4
    三角形的周长:12.0,面积:6.0
    三角形直角边a的度数:37.0,b的度数:53.0
    

    4. 编程产生0~100(包含0和100)的三个随机数a、b、c,要求至少使用两种不同的方法,将三个数按从小到大的顺序排序

    方法一:

    import random
    
    a = random.randint(0, 100)
    b = random.randint(0, 100)
    c = random.randint(0, 100)
    
    print(str.format("原始值:{0},{1},{2}", a, b, c))
    
    if(a > b): a,b = b,a
    if(a > c): a,c = c,a
    if(b > c): b,c = c,b
    
    print(str.format("增序:{0},{1},{2}", a, b, c))
    

    方法二(使用内置函数max、min、sum):

    import random
    
    a = random.randint(0, 100)
    b = random.randint(0, 100)
    c = random.randint(0, 100)
    
    print(str.format("原始值:{0},{1},{2}", a, b, c))
    
    maxx = max(a, b, c)
    minx = min(a, b, c)
    median = sum([a, b, c]) - minx - maxx
    
    print(str.format("增序:{0},{1},{2}", minx, median, maxx))
    

    方法三(使用内置函数sorted):

    >>> import random
    >>> a = random.randint(0,100)
    >>> b = random.randint(0,100)
    >>> c = random.randint(0,100)
    >>> print("init value: {0} , {1} , {2}".format(a,b,c))
    init value: 17 , 6 , 59
    >>> sorted([a,b,c])
    [6, 17, 59]
    

    5. 编程计算有固定工资收入的党员每月所缴纳的党费。

    工资基数3000元及以下者,交纳工资基数的0.5%
    工资基数3000~5000元者,交纳工资基数的1%
    工资基数在5000~10000元者,交纳工资基数的1.5%
    工资基数超过10000元者,交纳工资基数的2%

    salary = float(input("请输入有固定工资收入的党员的月工资:"))
    if salary <= 3000: dues = salary*0.005
    elif salary <= 5000: dues = salary*0.01
    elif salary <= 10000: dues = salary*0.15
    else: dues = salary*0.02
    
    print("交纳党费:",dues)
    

    运行:

    请输入有固定工资收入的党员的月工资:10001
    交纳党费: 200.02
    

    6. 编程实现袖珍计算器,要求输入两个操作数和一个操作符(+、-、*、/、%),根据操作符输出运算结果。注意/和%运算符的零异常问题

    a = float(input("请输入操作数(左):"))
    b = float(input("请输入操作数(右):"))
    operator = input("请输入操作符(+、-、*、/、%):")
    
    if(b == 0 and (operator == '/' or operator == '%')):
        print("分母为零,异常!")
    else:
        if operator == '+': result = a+b
        elif operator == '-': result = a-b
        elif operator == '*': result = a*b
        elif operator == '/': result = a/b
        elif operator == '%': result = a%b
        print("{0} {1} {2}= {3}:".format(a,operator,b,result))
    

    运行:

    请输入操作数(左):10
    请输入操作数(右):5
    请输入操作符(+、-、*、/、%):+
    10.0 + 5.0= 15.0:
    

    7. 输入三角形的3条边a、b、c,判断此3边是否可以构成三角形。若能,进一步判断三角形的性质,即为等边、等腰、直角或其他三角形

    a = float(input("请输入三角形的边a:"))
    b = float(input("请输入三角形的边b:"))
    c = float(input("请输入三角形的边c:"))
    
    if(a > b): a,b = b,a
    if(a > c): a,c = c,a
    if(b > c): b,c = c,b
    
    result = "三角形"
    if(not(a>0 and b>0 and c>0 and a+b>c)):
        result = '此三边无法构成三角形'
    else:
        if a == b == c: result = '等边三角形'
        elif(a==b or a==c or b==c): result = '等腰三角形'
        elif(a*a+b*b == c*c): result = '直角三角形'
    
    print(result)
    

    运行:

    请输入三角形的边a:3
    请输入三角形的边b:4
    请输入三角形的边c:5
    直角三角形
    

    8. 编程实现鸡兔同笼问题

    已知在同一个笼子里共有h只鸡和兔,鸡和兔的总脚数为f,其中h和f由用户输入,求鸡和兔各有多少只?要求使用两种方法:一是求解方程;二是利用循环进行枚举测试

    h = int(input("请输入总头数:"))
    f = int(input("请输入总脚数:"))
    
    def fun1(h,f):
        rabbits = f/2-h
        chicken = h-rabbits
        if(chicken < 0 or rabbits < 0): return '无解'
        return chicken,rabbits
    
    def fun2(h,f):
        for i in range(0,h+1):
            if(2*i + 4*(h-i) == f):return i,h-i
        return '无解'
    
    if(h>0 and f>0 and f % 2 == 0):
        if fun1(h,f)=='无解':
            print("无解")
        else:
            print("方法一:鸡:{0},兔:{1}".format(fun1(h,f)[0],fun1(h,f)[1]))
            print("方法二:鸡:{0},兔:{1}".format(fun2(h,f)[0],fun2(h,f)[1]))
    else:
        print('输入的数据无意义')    
    

    运行:

    请输入总头数:100
    请输入总脚数:100
    无解
    

    9. 输入任意实数x,计算ex的近似值,直到最后一项的绝对值小于10-6为止

    ex = 1 + x + x2/2 + x3/3! + x4/4! + … + xn/n!

    x = int(input("请输入任意实数:"))
    
    e = 1
    i = 1
    t = 1
    a = 1
    while(a >= 10e-6):
        t *= i
        a = pow(x,i)/t
        e += a
        i += 1
    
    print(e)
    

    运行:

    请输入任意实数:1
    2.7182815255731922
    

    我发现了在Python中10e-6pow(10,-6)是有差别的,将上述代码中的10e-6改为pow(10,-6),输出结果会有细微的差别

    运行:

    请输入任意实数:1
    2.7182818011463845
    

    10. 输入任意实数a(a>=0),用迭代法求x=√a,要求计算的相对偏差小于10-6

    求平方根的公式:

    Xn+1 = 0.5(Xn + a/Xn)

    import math
    
    a = int(input("请输入任意实数a(>=0):"))
    
    x = a / 2
    y = (x + a/x) / 2
    
    while(abs(y-x) >= pow(10,-6)):
        x = y
        y = (x + a/x) / 2
    
    print(y)
    

    运行:

    请输入任意实数a(>=0):2
    1.414213562373095
    

    11. 即有一个数,用3除余2,用5除余3,用7除余2,请问0~1000中这样的数有哪些?

    我国古代有位大将,名叫韩信。他每次集合部队,只要求部下先后按1-3,1-5,1-7报数,然后再报告一下各队每次报数的余数,他就知道到了多少人。他的这种巧妙算法被人们称作“鬼谷算”,也叫“隔墙算”,或称为“韩信点兵”,外国人还称它为“中国余数定理”。

    for i in range(0,1001):
        if((i % 3 == 2 )and (i % 5 == 3) and (i % 7 == 2)): print(i, end="  ")
    

    运行:

    23  128  233  338  443  548  653  758  863  968
    

    12. 一球从100米的高度自由下落,每次落地后反弹回原高度的一半,再落下。求小球在第10次落地时共经过多少米?第10次反弹多高

    规律:
    第一次下落时的高度:100
    第二次下落时的高度(第一次反弹的高度):50
    第三次下落时的高度(第二次反弹的高度):25

    n = 10
    
    h_down = 100
    h_up = 0
    sum = 0
    for i in range(1,n+1):
        sum += h_down+h_up
        h_down = h_up = h_down/2
    
    print("小球在第十次落地时共经过:{0}米,第十次反弹高度:{1}米".format(sum,h_up))    
    

    运行:

    小球在第十次落地时共经过:299.609375米,第十次反弹高度:0.09765625米
    

    13. 猴子吃桃问题

    猴子第一天摘下若干个桃子,当天吃掉一半多一个;第二天接着吃了剩下的桃子的一半多一个;以后每天都吃了前一天剩下的桃子的一半多一个。到第八天发现只剩一个桃子了。请问猴子第一天共摘了多少个桃子?

    这是一个递推问题

    某天所剩桃子数x
    后一天所剩桃子数y = x - (x/2+1) = x/2-1

    则x = 2(y+1)

    result = 1
    for i in range(8,0,-1):
        print("第{0}天桃子数:{1}".format(i,result))
        result = 2*(result+1)
    

    运行:

    第8天桃子数:1
    第7天桃子数:4
    第6天桃子数:10
    第5天桃子数:22
    第4天桃子数:46
    第3天桃子数:94
    第2天桃子数:190
    第1天桃子数:382
    

    14. 计算Sn = 1+11+111+…+111…111(最后一项是n个1)。n是一个随机产生的1~10(包括1和10)中的正整数

    import random
    
    n = random.randint(1,10)
    
    x = 1
    s = 0
    for i in range(1,n+1):
        s += x
        x = 10*x+1
    
    print("n = {0},sn = {1}".format(n,s))
    

    运行:

    n = 6,sn = 123456
    

    random.randint(a, b)

    • 生成指定范围内的整数
    • 范围:[a, b]

    案例研究:科学计算和数据分析

    https://blog.csdn.net/Zhangguohao666/article/details/103941448

    通过Python科学计算和数据分析库的安装和基本使用,了解使用Python进行科学计算的基本方法

    第五章 序列数据类型


    几个例题

    一:Python中内置的序列数据类型

    • 元组也称为定值表,用于存储固定不变的表
    • 列表也称为表,用于存储其值可变的表
    • 字符串是包括若干字符的序列数据,支持序列数据的基本操作
    • 字节序列数据是包括若干字节的序列。Python抓取网页时返回的页面通常为utf-8编码的字节序列。

    字节序列和字符串可以直接相互转换(字节编码和解码):

    >>> s1 = b'abc'
    >>> s1
    b'abc'
    >>> s1.decode("utf-8")
    abc
    
    >>> s2 = "中国"
    >>> s2.encode("utf-8")
    b'\xe4\xb8\xad\xe5\x9b\xbd'
    

    二:序列的切片操作示例

    >>> s = 'zgh666'
    >>> s[0]
    'z'
    >>> s[2]
    'h'
    >>> s[:3]
    'zgh'
    >>> s[1:3]
    'gh'
    >>> s[3:6]
    '666'
    >>> s[3:55]
    '666'
    >>> s[::-1]
    '666hgz'
    >>> s[3:2]
    ''
    >>> s[:]
    'zgh666'
    >>> s[::2]
    'zh6'
    

    三:序列的连接和重复操作

    • 通过连接操作符+可以连接两个序列,形成一个新的序列对象
    • 通过重复操作符*可以重复一个序列n次
    • 连接操作符和重复操作符也支持复合赋值运算,即:+=*=
    >>> x = 'zgh'
    >>> y = '666'
    >>> x + y
    'zgh666'
    >>> x *2
    'zghzgh'
    >>> x += y
    >>> x
    'zgh666'
    >>> y *= 3
    >>> y
    '666666666'
    

    四:序列的成员关系操作

    • in
    • not in
    • s.count(x)
      x在s中出现的次数
    • s.index(x)
      x在s中第一次出现的下标
    >>> s = "zgh666"
    >>> 'z' in s
    True
    >>> 'g' not in s
    False
    >>> s.count('6')
    3
    >>> s.index('6')
    3
    

    五:序列的排序操作

    sorted(iterable,key=None,reverse=False)

    >>> sorted(s)
    [1, 3, 5, 9]
    >>> sorted(s,reverse=True)
    [9, 5, 3, 1]
    
    >>> s = 'zGhZgH'
    >>> sorted(s)
    ['G', 'H', 'Z', 'g', 'h', 'z']
    >>> sorted(s,key=str.lower)
    ['G', 'g', 'h', 'H', 'z', 'Z']
    >>> sorted(s,key=str.lower,reverse=True)
    ['z', 'Z', 'h', 'H', 'G', 'g']
    

    六:序列的拆分

    1. 变量个数与序列长度相等
      若变量个数与序列的元素个数不一致,将导致ValueError
    >>> data = (118,'zgh',(100,100,100))
    >>> sid,name,(chinese,english,math) = data
    >>> sid
    118
    >>> name
    'zgh'
    >>> chinese
    100
    >>> english
    100
    >>> math
    100
    
    1. 变量个数与序列长度不等
      如果序列长度未知,可以使用*元组变量,将多个值作为元组赋值给元组变量。在一个赋值语句中,*元组变量只允许出现一次,否则将导致SyntaxError
    >>> first,second,third,*middles,last = range(10)
    >>> first
    0
    >>> second
    1
    >>> third
    2
    >>> middles
    [3, 4, 5, 6, 7, 8]
    >>> last
    9
    
    >>> first,*middles,last = sorted([58,60,60,100,70,70])
    >>> sum(middles)/len(middles)
    65.0
    
    1. 使用临时变量_
      如果只需要部分数据,序列的其它位置可以使用临时变量_
    >>> record = ['zgh','858990471@qq.com','17354364147','15272502101']
    >>> name,_,*phone = record
    >>> name
    'zgh'
    >>> phone
    ['17354364147', '15272502101']
    

    七:使用元组字面量,tuple创建元组实例对象的实例

    >>> t1 = 1,2,3
    >>> t1
    (1, 2, 3)
    
    >>> t2 = (4,5,6)
    >>> t2
    (4, 5, 6)
    
    >>> t3 = (9,)
    >>> t3
    (9,)
    

    如果元组中只有一个项目,后面的逗号不能省略。

    Python解释器把(1)解释为整数1,将(1,)解释为元组

    >>> t1 = tuple()
    >>> t1
    ()
    
    >>> t2 = tuple("zgh666")
    >>> t2
    ('z', 'g', 'h', '6', '6', '6')
    
    >>> t3 = tuple(['z','g','h'])
    >>> t3
    ('z', 'g', 'h')
    

    八:使用列表字面量,list创建列表实例对象的实例

    >>> l1 = []
    >>> l1
    []
    
    >>> l2 = ['zgh666']
    >>> l2
    ['zgh666']
    
    >>> l3 = [(1,2,3)]
    >>> l3
    [(1, 2, 3)]
    
    >>> l1 = list()
    >>> l1
    []
    
    >>> l2 = list(b'zgh666')
    >>> l2
    [122, 103, 104, 54, 54, 54]
    
    >>> l3 = list(b'aAbBcC')
    >>> l3
    [97, 65, 98, 66, 99, 67]
    

    补充:列表是可变对象,故用户可以改变列表对象中元素的值,也可以通过del删除某元素

    九:列表解析表达式示例

    使用列表解析表达式可以简单,高效地处理一个可迭代对象,并生成结果列表

    >>> [(i,i**2) for i in range(10)]
    [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)]
    
    >>> [i for i in range(10) if i%2==0]
    [0, 2, 4, 6, 8]
    
    >>> [(x,y,x*y) for x in range(1,4) for y in range(1,4) if x>=y]
    [(1, 1, 1), (2, 1, 2), (2, 2, 4), (3, 1, 3), (3, 2, 6), (3, 3, 9)]
    

    选择题:4、5、7、11、12

    4. Python语句序列“a = (1,2,3,None,(),[]);print(len(a))”的运行结果是

    >>> a = (1,2,3,None,(),[])
    >>> len(a)
    6
    

    5. Python语句序列“nums = set([1,2,2,3,3,3,4]);print(len(nums))”的运行结果是

    >>> nums = set([1,2,2,3,3,3,4])
    >>> nums
    {1, 2, 3, 4}
    >>> len(nums)
    4
    

    7. Python语句序列“s1=[4,5,6];s2=s1;s1[1]=0;print(s2)”的运行结果是

    Python中变量(如s1,s2)存储在栈中,存放的是地址
    [4,5,6]存储在堆中

    s1 = [4,5,6]即s1存储指向堆中[4,5,6]的地址
    s2 = s1地址赋值,即s2和s1都指向同一个地址
    所以对列表进行修改,两者的显示都会发生变化

    >>> s1 = [4,5,6]
    >>> s2 = s1
    >>> s1[1] = 0
    >>> s1
    [4, 0, 6]
    >>> s2
    [4, 0, 6]
    

    11. Python语句序列“s={‘a’,1,‘b’,2};print(s[‘b’])”的运行结果是

    A. 语法错B. ‘b’C. 1D. 2

    答案:A

    通过值访问集合是没有意义的,语法也不支持

    >>> s ={'a',1,'b',2}
    >>> print(s['b'])
    Traceback (most recent call last):
      File "<pyshell#29>", line 1, in <module>
        print(s['b'])
    TypeError: 'set' object is not subscriptable
    

    补充:集合set是无序不重复的,是无法通过下标访问的

    12. Python语句print(r"\nGood")的运行结果是

    A. 新行和字符串GoodB. r"\nGood"C. \nGoodD. 字符r、新行和字符串Good

    答案:C

    >>> print(r"\nGood")
    \nGood
    

    r""声明原始字符串

    填空题:1、5、6、12、13、14

    1. Python语句序列“fruits = [‘apple’,‘banana’,‘bear’];print(fruits[-1][-1])”的运行结果是

    注意:fruit[-1]是字符串’bear’
    所以:fruit[-1][-1]'bear[-1]'

    >>> fruits = ['apple','banana','pear']
    >>> fruits[-1]
    'pear'
    >>> fruits[-1][-1]
    'r'
    

    5. Python语句 print(’%d%%%d’%(3/2,3%2)) 的运行结果是

    >>> print('%d%%%d'%(3/2,3%2))
    1%1
    

    6. Python语句序列“s = [1,2,3,4];s.append([5,6]);print(len(s))”的运行结果是

    答案:5

    注意append()和extend()函数的区别
    s.append(x)将对象x追加到s尾部
    s.extend(x)将序列x追加到s尾部

    append

    >>> s = [1,2,3,4]
    >>> s.append([5,6])
    >>> s
    [1, 2, 3, 4, [5, 6]]
    >>> len(s)
    5
    

    extend

    >>> s = [1,2,3,4]
    >>> s.extend([5,6])
    >>> s
    [1, 2, 3, 4, 5, 6]
    >>> len(s)
    6
    

    12

    >>> s =('a','b','c','d','e')
    >>> s[2]
    'c'
    >>> s[2:3]
    ('c',)
    >>> s[2:4]
    ('c', 'd')
    >>> s[1::2]
    ('b', 'd')
    >>> s[-2]
    'd'
    >>> s[::-1]
    ('e', 'd', 'c', 'b', 'a')
    >>> s[-2:-1]
    ('d',)
    >>> s[-99:-5]
    ()
    >>> s[-99:-3]
    ('a', 'b')
    >>> s[::]
    ('a', 'b', 'c', 'd', 'e')
    >>> s[1:-1]
    ('b', 'c', 'd')
    

    13

    >>> s = [1,2,3,4,5,6]
    >>> s[:1] = []
    >>> s
    [2, 3, 4, 5, 6]
    
    >>> s[:2] = 'a'
    >>> s
    ['a', 4, 5, 6]
    
    >>> s[2:] = 'b'
    >>> s
    ['a', 4, 'b']
    
    >>> s[2:3] = ['x','y']
    >>> s
    ['a', 4, 'x', 'y']
    
    >>> del s[:1]
    >>> s
    [4, 'x', 'y']
    

    14

    >>> s = ['a','b']
    >>> s.append([1,2])
    >>> s
    ['a', 'b', [1, 2]]
    >>> s.extend('34')
    >>> s
    ['a', 'b', [1, 2], '3', '4']
    >>> s.extend([5,6])
    >>> s
    ['a', 'b', [1, 2], '3', '4', 5, 6]
    >>> s.insert(1,7)
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6]
    >>> s.insert(10,8)
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6, 8]
    >>> s
    ['a', 7, 'b', [1, 2], '3', '4', 5, 6]
    >>> s.remove('b')
    >>> s
    ['a', 7, [1, 2], '3', '4', 5, 6]
    >>> s[3:] =[]
    >>> s
    ['a', 7, [1, 2]]
    >>> s.reverse()
    >>> s
    [[1, 2], 7, 'a']
    >>> 
    

    思考题:2、3、5

    2. 阅读下面的Python语句,请问输出结果是什么?

    n = int(input('请输入图形的行数:'))
    
    for i in range(n,0,-1):
        print(" ".rjust(20-i),end=' ')
        for j in range(2*i-1):print(" * ",end=' ')
        print('\n')
    
    for i in range(1,n):
        print(" ".rjust(19-i),end=' ')
        for j in range(2*i+1):print(" * ",end=' ')
        print('\n')          
    

    运行一:

    请输入图形的行数:1
                         *  
    

    运行二:

    请输入图形的行数:2
                        *   *   *  
    
                         *  
    
                        *   *   *  
    

    运行三:

    请输入图形的行数:3
                       *   *   *   *   *  
    
                        *   *   *  
    
                         *  
    
                        *   *   *  
    
                       *   *   *   *   *  
    

    3. 阅读下面的Python语句,请问输出结果是什么?

    n = int(input('请输入上(或下)三角行数:'))
    
    for i in range(0,n):
        print(" ".rjust(19-i),end=' ')
        for j in range(2*i+1):print(" * ",end=' ')
        print('\n')
    
    for i in range(n-1,0,-1):
        print(" ".rjust(20-i),end=' ')
        for j in range(2*i-1):print(" * ",end=' ')
        print('\n')          
    

    运行:

    请输入上(或下)三角行数:4
                         *  
    
                        *   *   *  
    
                       *   *   *   *   *  
    
                      *   *   *   *   *   *   *  
    
                       *   *   *   *   *  
    
                        *   *   *  
    
                         *  
    

    5. 阅读下面的Python语句,请问输出结果是什么?

    先看这三句:

    >>> names1 = ['Amy','Bob','Charlie','Daling']
    >>> names2 = names1
    >>> names3 = names1[:]
    

    毫无疑问,此时names1,names2,names3的值都是[‘Amy’,‘Bob’,‘Charlie’,‘Daling’]
    但是

    >>> id(names1)
    2338529391368
    >>> id(names2)
    2338529391368
    >>> id(names3)
    2338529391560
    

    names1和names2指向同一个地址
    而names3指向另一个地址

    然后:

    >>> names2[0] = 'Alice'
    >>> names3[1] = 'Ben'
    >>> names1
    ['Alice', 'Bob', 'Charlie', 'Daling']
    >>> names2
    ['Alice', 'Bob', 'Charlie', 'Daling']
    >>> names3
    ['Amy', 'Ben', 'Charlie', 'Daling']
    

    最后:

    >>> sum = 0
    >>> for ls in(names1,names2,names3):
    	if ls[0] == 'Alice': sum+=1
    	if ls[1] == 'Ben':sum+=2
    
    	
    >>> print(sum)
    4
    

    上机实践:2~6

    2. 统计所输入字符串中单词的个数,单词之间用空格分隔

    s = input("请输入字符串:")
    
    num = 0
    for i in s:
        if((i >= 'a' and i <= 'z') or (i >= 'A' and i <= 'Z')):
            num += 1
    
    print("其中的单词总数:",num) 
    

    运行:

    请输入字符串:zgh666 ZGH6
    其中的单词总数: 6
    

    3. 编写程序,删除一个list里面重复元素

    方法一:利用set集合不重复的性质(但结果不能保证原来的顺序)

    l = [1,2,2,3,3,3,4,5,6,6,6]
    s = set(l)
    l = list(s)
    print(l)
    

    运行:

    [1, 2, 3, 4, 5, 6]
    

    方法二:既可以去除重复项,又可以保证原来的顺序

    def unique(items):
        items_existed = set()
        for item in items:
            if item not in items_existed:
                yield item
                items_existed.add(item)
    
    if __name__ == '__main__':
        a = [1, 8, 5, 1, 9, 2, 1, 10]
        a1 = unique(a)
        print(list(a1))
    
    

    运行结果:

    [1, 8, 5, 9, 2, 10]
    

    对代码的分析:

    • 可以看出,unique()函数返回的并不是items_existed,而是利用了yield

    在函数定义中,如果使用yield语句代替return返回一个值,则定义了一个生成器函数(generator)
    生成器函数是一个迭代器,是可迭代对象,支持迭代

    • a1 = unique(a) 这个函数返回的实际上是一个可迭代对象
      print(a1)得到的会是:<generator object unique at 0x0000016E23AF4F48>
    • 所以,要得到去掉重复后的列表的样子,需要将可迭代对象a1放在list()中
      运行:

    4. 编写程序,求列表[9,7,8,3,2,1,55,6]中的元素个数、最大值、最小值,以及元素之和、平均值。请思考有几种实现方法?

    内置函数:

    s = [9,7,8,3,2,1,55,6]
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(len(s),max(s),min(s),sum(s),sum(s)/len(s)))
    

    直接访问元素列表(for i in s…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = 0
    for i in s:
        sum += i
        length += 1
        if(i > max): max = i
        if(i < min): min = i
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    间接访问列表元素(for i in range(0,len(s))…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    for i in range(0,length):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    正序访问(i=0;while i<len(s)…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = 0
    while(i < length):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i += 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    反序访问(i=len(s)-1;while i>=0…):

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = length-1
    while(i >= 0):
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i -= 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    
    

    while True:…break

    s = [9,7,8,3,2,1,55,6]
    
    sum = 0
    max = s[0]
    min = s[0]
    length = len(s)
    
    i = 0
    while(True):
        if(i > length-1): break
        sum += s[i]
        if(s[i] > max): max = s[i]
        if(s[i] < min): min = s[i]
        i += 1
    
    print("元素个数:{0},最大值:{1},最小值:{2},和:{3},平均值:{4}".\
          format(length,max,min,sum,sum/length))
    

    运行:

    元素个数:8,最大值:55,最小值:1,和:91,平均值:11.375
    

    5. 编写程序,将列表[9,7,8,3,2,1,5,6]中的偶数变成它的平方,奇数保持不变

    l = [9,7,8,3,2,1,5,6]
    
    for i,value in enumerate(l):
        if(value % 2 == 0):l[i] = value**2
    
    print(l)
    

    运行:

    [9, 7, 64, 3, 4, 1, 5, 36]
    

    6. 编写程序,输入字符串,将其每个字符的ASCII码形成列表并输出

    s = input("请输入一个字符串:")
    l = list()
    for i in s:
        l.append(ord(i))
    
    print(l)
    

    运行:

    请输入一个字符串:zgh666
    [122, 103, 104, 54, 54, 54]
    

    案例研究:猜单词游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103948234

    通过猜单词游戏的设计和实现,帮助读者了解使用Python系列数据类型和控制流程

    第六章 输入和输出


    几个例题

    一:运行时提示输入密码

    输入密码时,一般需要不明显,则可以使用模块getpass,以保证用户输入的密码在控制台中不回显

    import getpass
    
    username = input("user:")
    password = getpass.getpass("password:")
    if(username == 'zgh' and password == '666'):
        print('logined!')
    else:
        print('failed!')
    
    input()#为了看到输出结果。因为执行完毕后,控制台会立马关闭
    

    注意:上面这个代码,如果使用IDLE执行,会因为安全问题而执行失败

    但是,在控制台中执行就没问题,看输出结果(可以看到,输入的密码不会显示出来):

    user:zgh
    password:
    logined!
    

    二:重定向标准输出到一个文件的示例

    这种重定向由控制台完成,而与Python本身无关。

    格式:
    程序 > 输出文件

    其目的是将显示屏从标准输出中分离,并将输出文件与标准输出关联,即程序的执行结果将写入输出文件,而不是发送到显示屏中显示

    首先准备一个test.py文件(代码如下)

    import sys,random
    
    n = int(sys.argv[1])
    for i in range(n):
        print(random.randrange(0,100))
    

    然后在PowerShell中:python test.py 100 > scores.txt
    记住,切记,一定要注意:千万能省略python,这样写./test.py 100 > scores.txt会出现问题,生成的scores文件中会没有任何内容!!!(原因未知)

    然后在当前目录下,100个[0,100)范围内的的整数生成在scores.txt文件中了

    三:重定向文件到标准输入

    格式:
    程序 < 输入文件

    其目的是将控制台键盘从标准输入中分离,并将输入文件与标准输入关联,即程序从输入文件中读取输入数据,而不是从键盘中读取输入数据

    准备一个average.py文件(代码如下)

    import sys
    
    total =0.0
    count = 0
    for line in sys.stdin:
        count += 1
        total += float(line)
    
    avg = total/count
    print("average:",avg)
    

    然后问题总是不期而至,
    在PowerShell中:python average.py < scores.txt,会报错,PowerShell会提示你:“<”运算符是为将来使用而保留的
    很无奈,我只能使用cmd了,然后得出结果

    四:管道

    格式:
    程序1 | 程序2 | 程序3 | … | 程序4

    其目的是将程序1的标准输出连接到程序2的标准输入,
    将程序2的标准输出连接到程序3的标准输入,以此类推

    例如:
    打开cmd,输入python test.py 100 | average.py,其执行结果等同于上面两个例子中的命令

    使用管道更加简洁,且不用创建中间文件,从而消除了输入流和输出流可以处理的数据大小的限制,执行效率更高

    五:过滤器

    1. 使用操作系统实用程序more逐屏显示数据

    2. 使用操作系统实用程序sort排序输出数据

    more和sort都可以在一个语句中使用

    填空题:1、2

    print(value, ..., sep = ' ', end = '\n', file = sys.stdout, flush = False)

    1. sep(分隔符,默认为空格)
    2. end(换行符,即输入的末尾是个啥)
    3. file(写入到指定文件流,默认为控制台sys.stdout)
    4. flush(指定是否强制写入到流)

    1

    >>> print(1,2,3,4,5,sep='-',end='!')
    1-2-3-4-5!
    

    2

    >>> for i in range(10):
    	print(i,end=' ')
    
    	
    0 1 2 3 4 5 6 7 8 9 
    

    例题及上机实践:2~5

    2. 尝试修改例6.2编写的命令行参数解析的程序,解析命令行参数所输入边长的值,计算并输出正方形的周长和面积

    argparse模块用于解析命名的命令行参数,生成帮助信息的Python标准模块

    例6.2:解析命令行参数所输入的长和宽的值,计算并输出长方形的面积

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--length', default = 10, type = int, help = '长度')
    parser.add_argument('--width', default = 5, type = int, help = '宽度')
    
    args = parser.parse_args()
    area = args.length * args.width
    print('面积 = ', area)
    
    input()#加这一句是为了可以看到输出结果
    

    输出:面积 = 50

    如果在执行这个模块时,加入两个命令行参数

    输出:面积 = 36

    基本上看了上面这个例子后,就可以理解argparse的用法了

    本题代码:

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--length', default = 10, type = int, help = '长度')
    
    args = parser.parse_args()
    area = args.length ** 2
    perimeter = 4 * args.length
    print('面积 = {0},周长 = {1}'.format(area,perimeter))
    
    input()#加这一句是为了可以看到输出结果
    
    

    在PowerShell中输入.\test.py
    不给命令行参数,输出是以默认值来计算的
    输出:面积 = 100,周长 = 40

    给命令行参数:.\test.py --length 1
    输出:面积 = 1,周长 = 4

    3. 尝试修改例6.8编写读取并输出文本文件的程序,由命令行第一个参数确认所需输出的文本文件名

    f = open(file, mode = 'r' , buffering = -1, encoding = None)

    1. file是要打开或创建的文件名,如果文件不在当前路径,需指出具体路径
    2. mode是打开文件的模式,模式有:
      ‘r’(只读)
      ‘w’(写入,写入前删除就内容)
      ‘x’(创建新文件,如果文件存在,则导致FileExistsError)
      ‘a’(追加)
      ‘b’(二进制文件)
      ‘t’(文本文件,默认值)
      ‘+’(更新,读写)
    3. buffering表示是否使用缓存(缓存为-1,表示使用系统默认的缓冲区大小)
    4. encoding是文件的编码

    例6.8:读取并输出文本文件

    import sys
    
    filename = sys.argv[0]#就读取本文件,骚的呀皮
    f = open(filename, 'r', encoding = 'utf-8')
    
    line_no = 0
    while True:
        line_no += 1
        line = f.readline()
        if line:
            print(line_no, ":", line)
        else:
            break
    f.close()       
    

    输出(代码输出的就是本python文件):

    1 : import sys
    
    2 : 
    
    3 : filename = sys.argv[0]#就读取本文件,骚的呀皮
    
    4 : f = open(filename, 'r', encoding = 'utf-8')
    
    5 : 
    
    6 : line_no = 0
    
    7 : while True:
    
    8 :     line_no += 1
    
    9 :     line = f.readline()
    
    10 :     if line:
    
    11 :         print(line_no, ":", line)
    
    12 :     else:
    
    13 :         break
    
    14 : f.close()
    
    15 :         
    
    

    本题代码:

    对例题代码进行些许修改就可以了,首先将上例中的第二个语句改为:filename = sys.argv[0],再考虑下面怎么进行

    准备一个用来测试的文件test.txt:

    对于这个文件要注意一点(你们很可能回出现这个问题!!!),win10默认创建的文本文件的字符编码是ANSI

    代码怎么写,有两种:

    1. 将test.txt文本文件的编码修改为utf-8,代码如上所说
      记事本方式打开test.txt文件,点击文件,点击另存为,看到下方的编码(修改为utf-8)
    2. test.txt就用默认的ANSI编码方式,再将上例代码的第三个语句修改为f = open(filename, 'r', encoding = 'ANSI')

    在PowerShell中输入:./test.py test.txt
    输出:

    1 : 大家好
    
    2 : 我是Zhangguohao666
    
    3 : 如果本文章对大家有帮助,请点赞支持一下
    
    4 : 还有:
    
    5 : 如果发现了什么问题,请在评论区指出,我会积极改进
    

    4. 尝试修改例6.9编写利用with语句读取并输出文本文件的程序,由命令行第一个参数确认所需输出的文本文件名

    为了简化操作,Python语言中与资源相关的对象可以实现上下文管理协议,可以使用with语句,确保释放资源。
    with open(file,mode) as f:

    例6.9:利用with语句读取并输出文本文件

    import sys
    
    filename = sys.argv[0]
    
    line_no = 0
    with open(filename, 'r', encoding = 'utf-8') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
    

    基本上,看这个例子,就可以上手with语句了

    本题代码:

    还是上一题准备的文本文件,
    代码一(文本文件的编码为默认的ANSI):

    import sys
    
    filename = sys.argv[1]
    
    line_no = 0
    with open(filename, 'r', encoding = 'ANSI') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
          
    

    代码二(将文本文件的编码修改为utf-8):

    import sys
    
    filename = sys.argv[1]
    
    line_no = 0
    with open(filename, 'r', encoding = 'utf-8') as f:
        for line in f:
            line_no += 1
            print(line_no, ":", line)
    f.close()
          
    
    

    本题的输出,我再不要脸的放一次吧:

    1 : 大家好
    
    2 : 我是Zhangguohao666
    
    3 : 如果本文章对大家有帮助,请点赞支持一下
    
    4 : 还有:
    
    5 : 如果发现了什么问题,请在评论区指出,我会积极改进
    

    5. 尝试修改例6.12编写标准输出流重定向的程序,从命令行第一个参数中获取n的值,然后将0-n,0-n的2倍值,2的0-n次幂的列表打印输出到out.log文件中

    例6.12:从命令行第一个参数中获取n的值,然后将0-n,2的0-n次幂的列表打印输出到out.log文件中

    1. 标准输入流文件对象:sys.stdin,
      默认值为sys.__stdin__
    2. 标准输出流文件对象:sys.stdout,
      默认值为sys.__stdout__
    3. 错误输出流文件对象(标准错误流文件对象):sys.stderr
      默认值为sys.__stderr__

    书中给的代码是这样的:

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ', str(power))
        power = 2*power
        i += 1
    sys.stdout = sys.__stdout__
    

    如果使用的编辑器是PyCharm(现在大多数编辑器会帮你对代码进行优化和处理一些隐患),运行书中的这个代码没有问题。

    但是:
    若使用的编辑器是python自带的IDLE,运行这个代码有问题!

    第一:out.log文件会生成,但是没有东西
    (发现文件关闭不了(就是×不掉),
    确定是文件没关闭(f.close())的原因)

    第二:控制台没有输出’done’语句(估计是IDLE编辑器处理不了__stdout__这个值)

    经过研究后,发现(基于IDLE编辑器):
    如果在上面的代码中加入f.close()后,该输入的东西都成功输入进out.log文件了,
    但是,
    还有一个问题
    控制台依旧没有输出’done’语句
    经过一步步的断点调试(就是手动写print)
    发现sys.stdout = sys.__stdout__不会执行

    然后进行改动后,就可以了,代码如下:
    (既然__stdout__不好使,就使用中间变量)

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    output = sys.stdout
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ', str(power))
        power = 2*power
        i += 1
    
    f.close()
    sys.stdout = output
    print('done!')#这一句是用来检测上面的代码是否成功执行
    
    

    问题虽然解决,但是原因没有彻底弄清楚,求助。。。。。。

    本题代码:

    import sys
    
    n = int(sys.argv[1])
    power = 1
    i = 0
    
    output = sys.stdout
    f = open('out.log', 'w')
    sys.stdout = f
    
    while i <= n:
        print(str(i), ' ',  str(2*i),  ' ', str(power))
        power = 2*power
        i += 1
    
    f.close()
    sys.stdout = output
    print('done!')#这一句是用来检测上面的代码是否成功执行
    
    

    比如时输入的命令行参数是6
    输出:

    案例研究:21点扑克牌游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103948545

    通过21点扑克牌游戏的设计和实现,了解使用Python数据类型、控制流程和输入输出

    第七章 错误和异常处理


    Python语言采用结构化的异常处理机制捕获和处理异常

    而我感觉,Python在这方面的知识点其实和Java的差不多

    几个例题

    一:程序的错误和异常处理

    1. 语法错误

    指源代码中的拼写错误,这些错误导致Python编译器无法把Python源代码转换为字节码,故也称之为编译错误

    1. 运行时错误

    在解释执行过程中产生的错误

    例如:

    • 程序中没有导入相关的模块,NameError
    • 程序中包括零除运算,ZeroDivisionError
    • 程序中试图打开不存在的文件,FileNotFoundError
    1. 逻辑错误

    程序可以执行(程序运行本身不报错),但执行结果不正确。
    对于逻辑错误,Python解释器无能为力,需要用户根据结果来调试判断

    大部分由程序错误而产生的错误和异常一般由Python虚拟机自动抛出。另外,在程序中如果判断某种错误情况,可以创建相应的异常类的对象,并通过raise语句抛出

    >>> a = -1
    >>> if(a < 0): raise ValueError("数值不能为负数")
    
    Traceback (most recent call last):
      File "<pyshell#9>", line 1, in <module>
        if(a < 0): raise ValueError("数值不能为负数")
    ValueError: 数值不能为负数
    >>> 
    

    在程序中的某个方法抛出异常后,Python虚拟机通过调用堆栈查找相应的异常捕获程序。如果找到匹配的异常捕获程序(即调用堆栈中的某函数使用try…except语句捕获处理),则执行相应的处理程序(try…except语句中匹配的except语句块)

    如果堆栈中没有匹配的异常捕获程序,则Python虚拟机捕获处理异常,在控制台打印出异常的错误信息和调用堆栈,并中止程序的执行

    二:try …except…else…finally

    try:
    	可能产生异常的语句
    except Exception1:
    	发生Exception1时执行的语句
    except (Exception2,Exception3):
    	发生Exception2或Exception3时执行的语句
    except Exception4 as e:
    	发生Exception4时执行的语句,Exception4的实例是e
    except:
    	捕获其他所有异常
    else:
    	无异常时执行的语句
    finally:
    	不管异常发生与否都保证执行的语句			
    

    except语句可以写多个,但是要注意一点:系统是自上而下匹配发生的异常,所以用户需要将带有最具体的(即派生类程度最高的)异常类的except写在前面

    三:创建自定义异常,处理应用程序中出现的负数参数的异常

    自定义异常类一般继承于Exception或其子类。自定义异常类的名称一般以Error或Exception为后缀

    >>> class NumberError(Exception):
        def __init__(self,data):
            Exception.__init__
            (self,data)
            self.data = data
        def __str__(self):
            return self.data + ':非法数值(<0)'
    
    >>> 
    >>> def total(data):
        total = 0
        for i in data:
            if i < 0: raise NumberError(str(i))
            total += 1
        return total
    
    >>> 
    >>> data1 = (44, 78, 90, 80, 55)
    >>> print("sum: ",total(data1))
    sum:  5
    >>> 
    >>> data2 = (44, 78, 90, 80, -1)
    >>> print("sum: ",total(data2))
    Traceback (most recent call last):
      File "<pyshell#24>", line 1, in <module>
        print("sum: ",total(data2))
      File "<pyshell#18>", line 4, in total
        if i < 0: raise NumberError(str(i))
    NumberError: -1:非法数值(<0>>> 
    

    四:断言处理

    用户在编写程序时,在调试阶段往往需要判断代码执行过程中变量的值等信息:

    1. 用户可以使用print()函数打印输出结果
    2. 也可以通过断点跟踪调试查看变量
    3. 但使用断言更加灵活

    assert语句和AssertionError

    断言的声明:

    • assert <布尔表达式>
      即:if __debug__: if not testexpression: raise AssertionError
    • assert <布尔表达式>,<字符串表达式>
      即:if __debug__: if not testexpression: raise AssertionError(data)
      字符串表达式(即data)是断言失败时输出的失败消息

    __debug__也是布尔值,Python解释器有两种:调试模式和优化模式

    • 调试模式:__debug__ == True
    • 优化模式:__debug__ == False

    在学习中,对于执行一个py模块(比如test.py)我们通常在cmd中这么输入python test.py,而这默认是调试模式。
    如果我们要使用优化模式来禁用断言来提高程序效率,我们可以加一个运行选项-O,在控制台中这么输入python -O test.py

    看一下断言的示例吧,理解一下用法:

    a =int(input("a: "))
    b =int(input("b: "))
    assert b != 0, '除数不能为零'
    c = a/b
    print("a/b = ", c)
    

    cmd出场:
    输入正确数值时:

    输入错误数值时:

    禁用断言,并且输入错误数值时:

    案例研究:使用调试器调试Python程序

    https://blog.csdn.net/Zhangguohao666/article/details/103948568

    了解使用Python调试器调试程序的方法

    第八章 函数和函数式编程


    一些知识点总结和几个例题

    Python中函数的分类:

    1. 内置函数
      在程序中可以直接使用
    2. 标准库函数
      Python语言安装程序同时会安装若干标准库,例如math、random等
    3. 第三方库函数
      Python社区提供了许多其它高质量的库,在下载、安装这些库后,通过import语句可以导入库
    4. 用户自定义函数
    • 函数名为有效的标识符(命名规则为全小写字母,可以使用下划线增加可阅读性,例如my_func()
    • 函数可以使用return返回值
      如果函数体中包含return语句,则返回值
      否则不返回,即返回值为空(None),无返回值的函数相当于其它编程语言中的过程

    调用函数之前程序必须先执行def语句,创建函数对象

    • 内置函数对象会自动创建
    • import导入模块时会执行模块中的def语句,创建模块中定义的函数
    • Python程序结构顺序通常为import语句>函数定义>全局代码

    一:产生副作用的函数,纯函数

    打印等腰三角形

    n = int(input("行数:"))
    
    def print_star(n):
        print((" * " * n).center(50))
    
    for i in range(1, 2*n, 2):
        print_star(i)
    

    输出:

    行数:5
                            *                         
                         *  *  *                      
                      *  *  *  *  *                   
                   *  *  *  *  *  *  *                
                *  *  *  *  *  *  *  *  *             
    

    上面代码中的print_star()是一个产生副作用的函数,其副作用是向标准输出写入若干星号

    • 副作用:例如读取键盘输入,产生输出,改变系统的状态等
    • 在一般情况下,产生副作用的函数相当于其它程序设计语言中的过程,可以省略return语句

    定义计算并返回第n阶调和数(1+1/2+1/3+…+1/n)的函数,输出前n个调和数

    def harmonic(n):
        total = 0.0
        for i in range(1, n+1):
            total += 1.0/i
        return total
    
    n = int(input("n:"))
    
    print("输出前n个调和数的值:")
    for i in range(1, n+1):
        print(harmonic(i))
    

    输出:

     n:8
    输出前n个调和数的值:
    1.0
    1.5
    1.8333333333333333
    2.083333333333333
    2.283333333333333
    2.4499999999999997
    2.5928571428571425
    2.7178571428571425         
    

    上面代码中的harmonic()是纯函数

    纯函数:给定同样的实际参数,其返回值唯一,且不会产生其它的可观察到的副作用

    注意:编写同时产生副作用和返回值的函数通常被认为是不良编程风格,但有一个例外,即读取函数。例如,input()函数既可以返回一个值,又可以产生副作用(从标准输入中读取并消耗一个字符串)

    二:传递不可变对象、可变对象的引用

    • 实际参数值默认按位置顺序依次传递给形式参数。如果参数个数不对,将会产生错误

    在调用函数时:

    1. 若传递的是不可变对象(例如:int、float、bool、str对象)的引用,则如果函数体中修改对象的值,其结果实际上是创建了一个新的对象
    i = 1
    
    def func(i,n):
        i += n
        return i
    
    print(i)#1
    func(i,10)
    print(i)#1
    

    执行函数func()后,i依旧为1,而不是11

    1. 若传递的是可变对象(例如:list对象)的引用,则在函数体中可以直接修改对象的值
    import random
    
    def shuffle(a):
        n = len(a)
        for i in range(n):
            r = random.randrange(i,n)
            a[i],a[r] = a[r],a[i]
    
    a = [1,2,3,4,5]
    print("初始:",a)
    shuffle(a)
    print("调用函数后:",a)
    

    输出:

    初始: [1, 2, 3, 4, 5]
    调用函数后: [1, 5, 4, 3, 2]
    

    三:可选参数,命名参数,可变参数,强制命名参数

    可选参数

    • 在声明函数时,如果希望函数的一些参数是可选的,可以在声明函数时为这些参数指定默认值
    >>> def babbles(words, times=1):
    	print(words * times)
    
    	
    >>> babbles('Hello')
    Hello
    >>> 
    >>> babbles("Hello", 2)
    HelloHello
    >>> 
    

    注意到一点:必须先声明没有默认值的形参,然后再声明有默认值的形参,否则报错。 这是因为在函数调用时默认是按位置传递实际参数的。

    怎么理解上面那句话呢?

    默认是按位置传递实际参数(如果有默认值的形参在左边,无默认值的形参在右,那么在调用函数时,你的实参该怎么传递呢?)

    命名参数

    • 位置参数:当函数调用时,实参默认按位置顺序传递形参
    • 命名参数(关键字参数):按名称指定传入的参数
      参数按名称意义明确
      传递的参数与顺序无关
      如果有多个可选参数,则可以选择指定某个参数值

    基于期中成绩和期末成绩,按照指定的权重计算总评成绩

    >>> def my_sum(mid_score, end_score, mid_rate = 0.4):
    	score = mid_score*mid_rate + end_score*(1-mid_rate)
    	print(format(score,'.2f'))
    
    	
    >>> my_sum(80,90)
    86.00
    >>> my_sum(mid_score = 80,end_score = 90)
    86.00
    >>> my_sum(end_score = 90,mid_score = 80)
    86.00
    >>> 
    

    可变参数

    • 在声明函数时,可以通过带星号的参数(例如:def func(* param))向函数传递可变数量的实参,调用函数时,从那一点后所有的参数被收集为一个元组
    • 在声明函数时,可以通过带双星号的参数(例如:def func(** param))向函数传递可变数量的实参,调用函数时,从那一点后所有的参数被收集为一个字典

    利用带星的参数计算各数字的累加和

    >>> def my_sum(a,b,*c):
        total = a+b
        for i in c:
            total += i
        return total
    
    >>> print(my_sum(1,2))
    3
    >>> print(my_sum(1,2,3,4,5,6))
    21
    

    利用带星和带双星的参数计算各数字的累加和

    >>> def my_sum(a,b,*c,**d):
        total = a+b
        for i in c:
            total += i
        for key in d:
            total += d[key]
        return total
    
    >>> print(my_sum(1,2))
    3
    >>> print(my_sum(1,2,3,4))
    10
    >>> print(my_sum(1,2,3,4,male=1,female=2))
    13
    

    强制命名参数

    • 在带星号的参数后面声明参数会导致强制命名参数(Keyword-only),然后在调用时必须显式使用命名参数传递值
    • 因为按位置传递的参数默认收集为一个元组,传递给前面带星号的可变参数
    >>> def my_sum(*, mid_score, end_score, mid_rate = 0.4):
        score = mid_score*mid_rate + end_score*(1-mid_rate)
        print(format(score,'.2f'))
    
    >>> my_sum(mid_score=80,end_score=90)
    86.00
    >>> my_sum(end_score=90,mid_score=80)
    86.00
    >>> my_sum(80,90)
    Traceback (most recent call last):
      File "<pyshell#47>", line 1, in <module>
        my_sum(80,90)
    TypeError: my_sum() takes 0 positional arguments but 2 were given
    >>> 
    

    四:全局语句global示例,非局部语句nonlocal示例,输出局部变量和全局变量

    • 在函数体中可以引用全局变量,但是要为定义在函数外的全局变量赋值,需要使用global语句
    pi = 2.1415926
    e = 2.7182818
    
    def my_func():
        global pi
        pi = 3.14
        print("global pi = ", pi)
        e = 2.718
        print("local e = ", e)
    
    print('module pi = ', pi)
    print('module e = ', e)
    my_func()
    print('module pi = ', pi)
    print('module e = ', e)
    

    输出:

    module pi =  2.1415926
    module e =  2.7182818
    global pi =  3.14
    local e =  2.718
    module pi =  3.14
    module e =  2.7182818
    
    • 在函数体中可以定义嵌套函数,在嵌套函数中如果要为定义在上级函数体的局部变量赋值,可以使用nonlocal
    def outer_func():
        tax_rate = 0.17
        print('outer function tax rate is ',tax_rate)
        def inner_func():
            nonlocal tax_rate
            tax_rate = 0.01
            print('inner function tax rate is ',tax_rate)
        inner_func()
        print('outer function tax rate is ',tax_rate)
    
    outer_func()
    

    输出:

    outer function tax rate is  0.17
    inner function tax rate is  0.01
    outer function tax rate is  0.01
    
    • 输出局部变量和全局变量
    1. 内置函数locals(),局部变量列表
    2. 内置函数globals(),全局变量列表

    五:获取和设置最大递归数

    在sys模块中,函数getrecursionlimit()setrecursionlimit()用于获取和设置最大递归次数

    >>> import sys
    >>> sys.getrecursionlimit()
    1000
    >>> sys.setrecursionlimit(666)
    >>> sys.getrecursionlimit()
    666
    >>> 
    

    六:三个有趣的内置函数:eval()、exec()、compile()

    eval

    • 对动态表达式进行求值,返回值
    • eval(expression, globals=None, locals=None)
      expression是动态表达式的字符串
      globals和locals是求值时使用的上下文环境的全局变量和局部变量,如果不指定,则使用当前运行上下文
    >>> x = 2
    >>> str_func = input("请输入表达式:")
    请输入表达式:x**2+2*x+1
    >>> eval(str_func)
    9
    >>> 
    

    exec

    • 可以执行动态表达式,不返回值
    • exec(str, globals=None, locals=None)
    >>> exec("for i in range(10): print(i, end=' ')")
    0 1 2 3 4 5 6 7 8 9 
    >>> 
    

    compile

    • 编译代码为代码对象,可以提高效率
    • compile(source, filename, mode)
      source为代码语句的字符串;如果是多行语句,则每一行的结尾必须有换行符\n
      filename为包含代码的文件
      mode为编码方式,可以为'exec'(用于语句序列的执行),可以为'eval'(用于表达式求值),可以为'single'(用于单个交互语句)
    >>> co = compile("for i in range(10): print(i, end=' ')", '', 'exec')
    >>> exec(co)
    0 1 2 3 4 5 6 7 8 9 
    >>> 
    

    七:map(),filter()

    • map(f, iterable,…),将函数f应用于可迭代对象,返回结果为可迭代对象

    示例1:

    >>> def is_odd(x):
    	return x%2 == 1
    
    >>> list(map(is_odd,range(5)))
    [False, True, False, True, False]
    >>> 
    

    示例2:

    >>> list(map(abs,[1,-2,3,-4,5,-6]))
    [1, 2, 3, 4, 5, 6]
    >>> 
    

    示例3:

    >>> list(map(str,[1,2,3,4,5]))
    ['1', '2', '3', '4', '5']
    >>
    

    示例4:

    >>> def greater(x,y):
    	return x>y
    
    >>> list(map(greater,[1,5,7,3,9],[2,8,4,6,0]))
    [False, False, True, False, True]
    >>> 
    
    • filter(f, iterable),将函数f应用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,返回结果为可迭代对象

    示例1(返回个位数的奇数):

    >>> def is_odd(x):
    	return x%2 == 1
    
    >>> list(filter(is_odd, range(10)))
    [1, 3, 5, 7, 9]
    >>> 
    

    示例2(返回三位数的回文):

    >>> list(filter(is_palindrome, range(100, 1000)))
    [101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
    >>> 
    

    八:Lambda表达式和匿名函数

    匿名函数广泛应用于需要函数对象作为参数、函数比较简单并且只使用一次的场合

    格式:

    lambda arg1,arg2... : <expression>
    

    其中,arg1、arg2等为函数的参数,<expression>为函数的语句,其结果为函数的返回值

    示例1(计算两数之和):

    >>> f = lambda x,y : x+y
    >>> type(f)
    <class 'function'>
    >>> f(1,1)
    2
    >>> 
    

    示例2(返回奇数):

    >>> list(filter(lambda x:x%2==1, range(10)))
    [1, 3, 5, 7, 9]
    >>> 
    

    示例3(返回非空元素):

    >>> list(filter(lambda s:s and s.strip(), ['A', '', 'B', None, 'C', ' ']))
    ['A', 'B', 'C']
    >>> 
    

    补充:

    • strip()用来去除头尾字符、空白符(\n,\r,\t,’’,即换行、回车、制表、空格)
    • lstrip()用来去除开头字符、空白符
    • rstrip()用来去除结尾字符、空白符

    再补充一点:

    • \n到下一行的开头
    • \r回到这一行的开头

    示例4(返回大于0的元素):

    >>> list(filter(lambda x:x>0, [1,0,-2,8,5]))
    [1, 8, 5]
    >>> 
    

    示例5(返回元素的平方):

    >>> list(map(lambda x:x*x, range(10)))
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> 
    

    九:operator模块和操作符函数

    Python内置操作符的函数接口,它定义了对应算术和比较等操作的函数,用于map()、filter()等需要传递函数对象作为参数的场合,可以直接使用而不需要使用函数定义或者Lambda表达式,使得代码更加简洁

    示例1(concat(x,y)对应于x+y):

    >>> import operator
    >>> a = 'hello'
    >>>> operator.concat(a, ' world')
    'hello world'
    

    实例2(operator.gt对应于操作符>):

    >>> import operator
    >>> list(map(operator.gt, [1,5,7,3,9],[2,8,4,6,0]))
    [False, False, True, False, True]
    >>> 
    

    十:functools.reduce(),偏函数functools.partial(),sorted()

    functools.reduce()

    functools.reduce(func, iterable[, iterable[, initializer]])

    • 使用指定的带两个参数的函数func对一个数据集合的所有数据进行下列操作:
    • 使用第一个和第二个数据作为参数用func()函数运算,得到的结果再与第三个数据作为参数用func()函数运算,依此类推,最后得到一个结果
    • 可选的initialzer为初始值

    示例:

    >>> import functools,operator
    >>> functools.reduce(operator.add, [1,2,3,4,5])
    15
    >>> functools.reduce(operator.add, [1,2,3,4,5], 10)
    25
    >>> functools.reduce(operator.add, range(1,101))
    5050
    >>> 
    >>> functools.reduce(operator.mul, range(1,11))
    3628800
    

    偏函数functools.partial()

    functools.partial(func, *arg, **keywords)

    • 通过把一个函数的部分参数设置为默认值的方式返回一个新的可调用(callable)的partial对象
    • 主要用于设置预先已知的参数,从而减少调用时传递参数的个数

    示例(2的n次方):

    >>> import functools,math
    >>> pow2 = functools.partial(math.pow, 2)
    >>> list(map(pow2, range(11)))
    [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0]
    >>> 
    

    十一:sorted()

    sorted(iterable, *, key=None, reverse=False)

    • iterable是待排序的可迭代对象
    • key是比较函数(默认为None,按自然顺序排序)
    • reverse用于指定是否逆序排序

    示例1(数值。默认自然排序):

    >>> sorted([1,6,4,-2,9])
    [-2, 1, 4, 6, 9]
    >>> sorted([1,6,4,-2,9], reverse=True)
    [9, 6, 4, 1, -2]
    >>> sorted([1,6,4,-2,9], key=abs)
    [1, -2, 4, 6, 9]
    

    示例2(字符串,默认按字符串字典序排序):

    >>> sorted(['Dod', 'cat', 'Rabbit'])
    ['Dod', 'Rabbit', 'cat']
    >>> sorted(['Dod', 'cat', 'Rabbit'], key=str.lower)
    ['cat', 'Dod', 'Rabbit']
    >>> sorted(['Dod', 'cat', 'Rabbit'], key=len)
    ['Dod', 'cat', 'Rabbit']
    

    示例3(元组,默认按元组的第一个元素排序):

    >>> sorted([('Bob', 75), ('Adam', 92), ('Lisa', 88)])
    [('Adam', 92), ('Bob', 75), ('Lisa', 88)]
    >>> sorted([('Bob', 75), ('Adam', 92), ('Lisa', 88)], key=lambda t:t[1])
    [('Bob', 75), ('Lisa', 88), ('Adam', 92)]
    

    十二:函数装饰器

    这玩意就很有意思了,很Java语言中的注解是很相像的

    示例1:

    import time,functools
    
    def timeit(func):
        def wrapper(*s):
            start = time.perf_counter()
            func(*s)
            end = time.perf_counter()
            print('运行时间:', end - start)
        return wrapper
    
    @timeit
    def my_sum(n):
        sum = 0
        for i in range(n): sum += i
        print(sum)
    
    if __name__ == '__main__':
        my_sum(10_0000)
    

    结果:

    4999950000
    运行时间: 0.013929100000000028
    

    怎么理解上面的代码呢?

    • 首先,timeit()返回的是wrapper,而不是执行(没有小括号)
    • @timeit相当于,在调用my_sum()的前一刻,会执行这么个语句:my_sum = timeit(my_sum)

    示例2:

    def makebold(fn):
        def wrapper(*s):
            return "<b>" + fn(*s) + "</b>"
        return wrapper
    
    def makeitalic(fn):
        def wrapper(*s):
            return "<i>" + fn(*s) + "</i>"
        return wrapper
    
    @makebold
    @makeitalic
    def htmltags(str1):
        return str1
    
    print(htmltags('Hello'))
    
    

    输出:

    <b><i>Hello</i></b>
    

    选择题:1~5

    1

    >>> print(type(lambda:None))
    <class 'function'>
    

    2

    >>> f = lambda x,y:x*y
    >>> f(12, 34)
    408
    

    3

    >>> f1 = lambda x:x*2
    >>> f2 = lambda x:x**2
    >>> print(f1(f2(2)))
    8
    

    4

    >>> def f1(p, **p2):
    	print(type(p2))
    
    	
    >>> f1(1, a=2)
    <class 'dict'>
    

    5

    >>> def f1(a,b,c):
    	print(a+b)
    
    	
    >>> nums = (1,2,3)
    >>> f1(*nums)
    3
    

    思考题:4~11

    4

    >>> d = lambda p:p*2
    >>> t = lambda p:p*3
    >>> x = 2
    >>> x = d(x)
    >>> x = t(x)
    >>> x = d(x)
    >>> print(x)
    24
    

    5

    >>> i = map(lambda x:x**2, (1,2,3))
    >>> for t in i:
    	print(t, end=' ')
    
    	
    1 4 9 
    

    6

    >>> def f1():
    	"simple function"
    	pass
    
    >>> print(f1.__doc__)
    simple function
    

    7

    >>> counter = 1
    >>> num = 0
    >>> def TestVariable():
    	global counter
    	for i in (1, 2, 3) : counter += 1
    	num = 10
    
    	
    >>> TestVariable()
    >>> print(counter, num)
    4 0
    

    8

    >>> def f(a,b):
    	if b==0 : print(a)
    	else : f(b, a%b)
    
    	
    >>> print(f(9,6))
    3
    None
    

    求最大公约数

    9

    >>> def aFunction():
    	"The quick brown fox"
    	return 1
    
    >>> print(aFunction.__doc__[4:9])
    quick
    

    10

    >>> def judge(param1, *param2):
    	print(type(param2))
    	print(param2)
    
    	
    >>> judge(1, 2, 3, 4, 5)
    <class 'tuple'>
    (2, 3, 4, 5)
    

    11

    >>> def judge(param1, **param2):
    	print(type(param2))
    	print(param2)
    
    	
    >>> judge(1, a=2, b=3, c=4, d=5)
    <class 'dict'>
    {'a': 2, 'b': 3, 'c': 4, 'd': 5}
    

    上机实践:2~5

    2. 编写程序,定义一个求阶乘的函数fact(n),并编写测试代码,要求输入整数n(n>=0)。请分别使用递归和非递归方式实现

    递归方式:

    def fact(n):
        if n == 0 :
            return 1
        return n*fact(n-1)
    
    n = int(input("请输入整数n(n>=0):"))
    print(str(n)+" ! =  " + str(fact(n)))
    
    

    非递归方式:

    def fact(n):
        t = 1
        for i in range(1,n+1):
            t *= i
        return t
    
    n = int(input("请输入整数n(n>=0):"))
    print(str(n)+" ! =  " + str(fact(n)))
    
    

    输出:

    请输入整数n(n>=0):5
    5 ! =  120
    

    3. 编写程序,定义一个求Fibonacci数列的函数fib(n),并编写测试代码,输出前20项(每项宽度5个字符位置,右对齐),每行输出10个。请分别使用递归和非递归方式实现

    递归方式:

    def fib(n):
        if (n == 1 or n == 2):
            return 1
        return fib(n-1)+fib(n-2)
    
    for i in range(1,21):
        print(str(fib(i)).rjust(5,' '),end = ' ')
        if i %10 == 0:
            print()
    

    非递归方式:

    def fib(n):
        if (n == 1 or n == 2):
            return 1
        n1 = n2 = 1
        for i  in range(3,n+1):
            n3 = n1+n2
            n1 = n2
            n2 = n3
        return n3
    
    for i in range(1,21):
        print(str(fib(i)).rjust(5,' '),end = ' ')
        if i %10 == 0:
            print()
    

    输出:

        1     1     2     3     5     8    13    21    34    55
       89   144   233   377   610   987  1597  2584  4181  6765
    

    4. 编写程序,利用可变参数定义一个求任意个数数值的最小值的函数min_n(a,b,*c),并编写测试代码。例如对于“print(min_n(8, 2))”以及“print(min_n(16, 1, 7, 4, 15))”的测试代码

    def min_n(a,b,*c):
        min_number = a if(a < b) else b
        for n in c:
            if n < min_number:
                min_number = n
        return min_number
    
    print(min_n(8, 2))
    print(min_n(16, 1, 7, 4, 15))
    

    输出:

    2
    1
    

    5. 编写程序,利用元组作为函数的返回值,求序列类型中的最大值、最小值和元素个数,并编写测试代码,假设测试代码数据分别为s1=[9, 7, 8, 3, 2, 1, 55, 6]、s2=[“apple”, “pear”, “melon”, “kiwi”]和s3="TheQuickBrownFox"

    def func(n):
        return (max(n),min(n),len(n))
        
    s1=[9, 7, 8, 3, 2, 1, 55, 6]
    s2=["apple", "pear", "melon", "kiwi"]
    s3="TheQuickBrownFox"
    
    for i in (s1,s2,s3):
        print("list = ", i)
        t = func(i)
        print("最大值 = {0},最小值 = {1},元素个数 = {2}".format(t[0], t[1], t[2]))
    

    输出:

    list =  [9, 7, 8, 3, 2, 1, 55, 6]
    最大值 = 55,最小值 = 1,元素个数 = 8
    list =  ['apple', 'pear', 'melon', 'kiwi']
    最大值 = pear,最小值 = apple,元素个数 = 4
    list =  TheQuickBrownFox
    最大值 = x,最小值 = B,元素个数 = 16
    

    案例研究:井字棋游戏

    https://blog.csdn.net/Zhangguohao666/article/details/103280740

    了解Python函数的定义和使用


    由于本文的内容太多了,导致了两个很不好的结果,
    一是:在网页中打开本篇博客的加载时间太长了,明显的卡顿很影响阅读体验;
    二是:本人在对本篇文章进行更新或者修改内容时,卡的要死。
    遂,
    将本文第八章后面的很多内容拆分到新的文章中,望大家理解


    第九章 面向对象的程序设计


    第十章 模块和客户端


    第十一章 算法与数据结构基础


    第十二章 图形用户界面


    我对图形用户界面基本无兴趣,无特殊情况,基本不打算碰这方面内容

    案例研究:简易图形用户界面计算器

    第十三章 图形绘制


    与上一章相同,我对于图形绘制的兴趣也基本没有,尝试做了2-7题,就完全没兴趣做下去了

    图形绘制模块:tkinter

    2. 参考例13.2利用Canvas组件创建绘制矩形的程序,尝试改变矩形边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 130, height = 70)
    c.pack()
    
    c.create_rectangle(10, 10, 60, 60, fill = 'red')
    c.create_rectangle(70, 10, 120, 60, fill = 'green', outline = 'blue', width = 5)
    
    

    创建画布对象:

    • root = Tk()
      创建一个Tk根窗口组件root
    • c = Canvas(root, bg = 'white', width = 130, height = 70)
      创建大小为200 * 100、背景颜色为白色的画布
    • c.pack()
      调用组件pack()方法,调整其显示位置和大小

    绘制矩形:

    c.create_rectangle(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • c.create_rectangle(70, 10, 120, 60, fill = 'green', outline = 'blue', width = 5)
      用蓝色边框、绿色填充矩形,边框宽度为5

    3. 参考例13.3利用Canvas组件创建绘制椭圆的程序,尝试修改椭圆边框样式、边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 280, height = 70)
    c.pack()
    
    c.create_oval(10, 10, 60, 60, fill = 'green')
    c.create_oval(70, 10, 120, 60, fill = 'green', outline = 'red', width = 5)
    c.create_oval(130, 25, 180, 45, dash = (10,))
    c.create_oval(190, 10, 270, 50, dash = (1,), width = 2)
    
    

    绘制椭圆

    c.create_oval(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • c.create_oval(70, 10, 120, 60, fill = 'green', outline = 'red', width = 5)
      绿色填充、红色边框,宽度为5
    • c.create_oval(130, 25, 180, 45, dash = (10,))
      虚线椭圆

    4. 参考例13.4利用Canvas组件创建绘制圆弧的程序,尝试修改圆弧样式、边框颜色以及填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 250, height = 70)
    c.pack()
    
    c.create_arc(10, 10, 60, 60, style = ARC)
    c.create_arc(70, 10, 120, 60, style = CHORD)
    c.create_arc(130, 10, 180, 60, style = PIESLICE)
    for i in range(0, 360, 60):
        c.create_arc(190, 10, 240, 60, fill = 'green', outline = 'red', start = i, extent = 30)
    
    

    绘制圆弧:

    c.create_arc(x0, y0, x1, y1, option, ...)
    
    • (x0,y0)是左上角的坐标
    • (x1,y1)是右下角的坐标
    • 选项start(开始角度,默认为0)和extend(圆弧角度,从start开始逆时针旋转,默认为90度)决定圆弧的角度范围
    • 选项start用于设置圆弧的样式

    5. 参考例13.5利用Canvas组件创建绘制线条的程序,尝试修改线条样式和颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 250, height = 70)
    c.pack()
    
    c.create_line(10, 10, 60, 60, arrow = BOTH, arrowshape = (3, 4, 5))
    c.create_line(70, 10, 95, 10, 120, 60, fill = 'red')
    c.create_line(130, 10, 180, 10, 130, 60, 180, 60, fill = 'green', width = 10, arrow = BOTH, joinstyle = MITER)
    c.create_line(190, 10, 240, 10, 190, 60, 240, 60, width = 10)
    
    

    绘制线条:

    c.create_line(x0, y0, x1, y1, ..., xn, yn, option, ...)
    
    • (x0,y0),(x1,y1),…,(xn,yn)是线条上各个点的坐标

    6. 参考例13.6利用Canvas组件创建绘制多边形的程序,尝试修改多边形的形状、线条样式和填充颜色

    from tkinter import *
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = 250, height = 70)
    c.pack()
    
    c.create_polygon(35, 10, 10, 60, 60, 60, fill = 'red', outline = 'green')
    c.create_polygon(70, 10, 120, 10, 120, 60, fill = 'white', outline = 'blue')
    c.create_polygon(130, 10, 180, 10, 180, 60, 130, 60, outline = 'blue')
    c.create_polygon(190, 10, 240, 10, 190, 60, 240, 60, fill = 'white', outline = 'black')
    
    

    绘制多边形:

    c.create_polygon(x0, y0, x1, y1, ..., option, ...)
    
    • (x0,y0),(x1,y1),…,(xn,yn)是多边形上各个顶点的坐标

    7. 参考例13.7利用Canvas组件创建绘制字符串和图形的程序,绘制y = cos(x) 的图形

    绘制字符串:

    c.create_text(x, y, option, ...)
    
    • (x,y)是字符串放置的中心位置

    y = sin(x)

    from tkinter import *
    import math
    
    WIDTH, HEIGHT = 510, 210
    ORIGIN_X, ORIGIN_Y = 2, HEIGHT/2 #原点
    
    SCALE_X, SCALE_Y = 40, 100 #x轴、y轴缩放倍数
    ox, oy = 0, 0
    x, y = 0, 0
    arc = 0 #弧度
    END_ARC = 360 * 2 #函数图形画两个周期
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = WIDTH, height = HEIGHT)
    c.pack()
    
    c.create_text(200, 20, text = 'y = sin(x)')
    c.create_line(0, ORIGIN_Y, WIDTH, ORIGIN_Y) 
    c.create_line(ORIGIN_X, 0, ORIGIN_X, HEIGHT) #绘制x轴,y轴
    for i in range(0, END_ARC+1, 10):
        arc = math.pi * i / 180
        x = ORIGIN_X + arc * SCALE_X
        y = ORIGIN_Y - math.sin(arc) * SCALE_Y
        c.create_line(ox, oy, x, y)
        ox, oy = x, y
    

    y = cos(x)

    from tkinter import *
    import math
    
    WIDTH, HEIGHT = 510, 210
    ORIGIN_X, ORIGIN_Y = 2, HEIGHT/2 #原点 
    
    SCALE_X, SCALE_Y = 40, 100 #x轴、y轴缩放倍数
    ox, oy = 0, 0
    x, y = 0, 0
    arc = 0 #弧度
    END_ARC = 360 * 2 #函数图形画两个周期
    
    root = Tk()
    c = Canvas(root, bg = 'white', width = WIDTH, height = HEIGHT)
    c.pack()
    
    c.create_text(200, 20, text = 'y = cos(x)')
    c.create_line(0, ORIGIN_Y, WIDTH, ORIGIN_Y) 
    c.create_line(ORIGIN_X, 0, ORIGIN_X, HEIGHT) 
    for i in range(0, END_ARC+1, 10):
        arc = math.pi * i / 180 
        x = ORIGIN_X + arc * SCALE_X
        y = ORIGIN_Y - math.cos(arc) * SCALE_Y
        c.create_line(ox, oy, x, y)
        ox, oy = x, y
    
    
    

    图形绘制模块:turtle


    后面章节内容:未完待续…

    第十四章 数值日期和时间处理


    第十五章 字符串和文本处理


    第十六章 文件和数据交换


    第十七章 数据访问


    第十八章 网络编程和通信


    第十九章 并行计算:进程、线程和协程


    第二十章 系统管理

    展开全文
  • 测验1:Python基本语法元素 知识点概要: 普遍认为Python语言诞生于1991年 ...字符串的正向递增和反向递减序号体系:正向是从左到右,0到n-1,反向是从右到左,-1到-n,举例str = "csdn" # str[0]就表示字符串c...

    测验1:Python基本语法元素

    知识点概要:

    • 普遍认为Python语言诞生于1991
    • Python语言中的缩进在程序中长度统一且强制使用,只要统一即可,不一定是4个空格(尽管这是惯例)
    • IPO模型指:Input Process Output
    • 字符串的正向递增和反向递减序号体系:正向是从左到右,0到n-1,反向是从右到左,-1到-n,举例
    str = "csdn" 
    #str[0]就表示字符串c, str[-1]表示"n"
    
    • Python的合法命名规则:命名包含字母,数字,下划线,但是首字符不能是数字
    • Python中获得用户输入的方式为:input()
    • Python中的保留字:type不是,是内置函数,def elif import 都是保留字
    • Python的数据类型有整数、列表、字符串等,但是不包括实数,实数是数学概念,在Python中对应着浮点数
    • 保留字if-elif-else用于表示分支结构,in用来进行成员判断
    • print()格式化输出,控制浮点数的小数点后两位输出应为:print("{:.2f}".format(XX)) :.2f哪一个都不能少

    编程测试:

    • Hello World 的条件输出:获得用户输入的一个整数,参考该整数值,打印输出"Hello World",要求:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      如果输入值是0,直接输出"Hello World"‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      如果输入值大于0,以两个字符一行方式输出"Hello World"(空格也是字符)‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      如果输入值小于0,以垂直方式输出"Hello World"
    # eval()函数可以将默认输入的字符串去掉双引号并进行表达式运算,如输入500+20,默认
    #得到的输入为一个字符串“500+20”,但是使用eval()函数我们得到的是一个整型数字:520
    Number = eval(input())
    if Number == 0:
        print("Hello World")
    elif Number > 0:
        print("He\nll\no \nWo\nrl\nd")
    else:
        for c in "Hello World":
            print(c)
    
    • 数值运算:获得用户输入的一个字符串,格式如下:M OP N ,其中,M和N是任何数字,OP代表一种操作,表示为如下四种:+, -, *, /(加减乘除)‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬根据OP,输出M OP N的运算结果,统一保存小数点后2位。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      注意:M和OP、OP和N之间可以存在多个空格,不考虑输入错误情况。
    print("{:.2f}".format(eval(input())))
    

    测验2:Python基本图形绘制

    知识点概要:

    • 正确引用turtle库的方式:
    import turtle
    #t是别名,可以更换其他名称
    import turtle as t 
    from turtle import setup
    from turtle import *
    

    import setup from turtle是不正确的

    • turtle库是一个直观有趣的图形绘制函数库,最早成功应用于LOGO编程语言,turtle绘图体系以水平右侧为绝对方位的0度,turtle坐标系的原点****默认在屏幕正中间
    • turtle.circle(-90,90)表示绘制一个半径为90像素的弧形,圆心在小海龟当前行进的右侧
    # circle(x,y)表示以x长度为半径,y为角度,
    #当前方向左侧x处为圆心画圆,其中x,y都可以是负数,相应取反
    #当前方向是水平向右的,对应直角坐标系中的x轴正方向
    #x为正,则圆心在y轴正方向上,y为正,逆时针画圆,圆弧角度为y
    #x为负则相反,圆心在y轴负方向上,y为正,顺时针画圆,圆弧角度为y
    
    • turtle.seth(to_angle)函数的作用是设置小海龟当前行进方向为to_angle,to_angle是角度的整数值
    • turtle.fd(distance)函数的作用是向小海龟当前行进方向前进distance距离
    • turtle.pensize(size)函数的作用是改变画笔的宽度为size像素
    • turtle**.circle**()函数不能绘制椭圆形
    • turtle.circle(x,y)函数绘制半圆,第二个参数y是180的奇数倍
    • turtle.penup()的别名有turtle.pu(),turtle.up()
    • turtle.colormode()的作用是设置画笔RGB颜色的表示模式
    • turtle.width()和turtle.pensize()都可以用来设置画笔尺寸
    • turtle.pendown()只是放下画笔,并不绘制任何内容
    • 改变turtle画笔的运行方向有left()、right()和seth()函数,bk()只能后退,但是不改变方向
    • turtle.done()用来停止画笔绘制,但绘图窗体不关闭,建议在每个turtle绘图最后增加turtle.done()
    • 循环相关保留字是:for…in和while,def用于定义函数

    编程测试:

    • turtle八边形绘制:使用turtle库,绘制一个八边形
    import turtle as t
    t.pensize(2)
    for i in range(8):
        t.fd(100)
        t.left(45)
    
    • turtle八角图形绘制:使用turtle库,绘制一个八角图形
    import turtle as t
    t.pensize(2)
    for i in range(8):
        t.fd(150)
        t.left(135)
    

    测验3:基本数据类型

    知识点概要:

    • pow(x,0.5)能够计算x的平方根,计算负数的平方根将产生复数
    • 字符串.strip()方法的功能是去掉字符串两侧指定的字符
    • 字符串.split()方法的功能是按照指定字符分隔字符串为数组
    • 字符串.repalce()方法的功能是替换字符串中特定字符
    • +操作符用来连接两个字符串序列
    • 字符串是一个连续的字符序列,使用\n可以实现打印字符信息的换行
    • val = pow(2,1000)
      #返回val结果的长度值要使用 len(str(val)),因为整型没有len()方法,要通过str()函数
      #将数字类型转换为字符串
    • 正确引用time库的方式如下:
    import time
    from time import strftime
    from time import *
    
    • Python语言的整数类型表示十进制(一般表示)二进制(0b或0B开头)八进制(0o或0O开头)十六进制(0x或0X开头)
    • %运算符的意思是取余数
    • 字符串切片操作:s[N:M],从N到M,但是不包括M
    name="Python语言程序设计课程"
    print(name[0],name[2:-2],name[-1])
    #输出结果为:P thon语言程序设计 程
    
    • print("{0:3}".format('PYTHON'))代码执行的结果是PYTHON,{0:3}表示输出的宽度是3,但是如果字符串长度超过3就以字符串长度显示

    编程测试:

    • 平方根格式化:获得用户输入的一个整数a,计算a的平方根,保留小数点后3位,并打印输出。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬输出结果采用宽度30个字符、右对齐输出、多余字符采用加号(+)填充,‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬如果结果超过30个字符,则以结果宽度为准
    a = eval(input())
    print("{:+>30.3f}".format(a**0.5)) 
    # +是填充字符 >是右对齐 30是宽度 .3f是保留小数点后3位
    #若平凡根后是一个复数,复数的实部和虚部都是浮点数,.3f可以将实部和虚部分别取三位小数
    
    • 字符串分段组合:获得输入的一个字符串s,以字符减号(-)分割s,将其中首尾两段用加号(+)组合后输出
    InputStr = input()
    strs = InputStr.split('-')
    print(strs[0]+'+'+strs[-1])
    print("{}+{}".format(strs[0], strs[-1]))
    #s.split(k)以k为标记分割s,产生一个列表
    #通过该题目,掌握split()方法的使用,注意:k可以是单字符,也可以是字符串
    

    测验4:程序的控制结构

    知识点概要:

    • for…in…中in的后面需要的是一个迭代类型(组合类型),{1;2;3;4;5}不是Python的有效数据类型
    • range(x,y)
    for i in range(0,2):
    	print(i)
    #输出结果为:0 1
    
    • 程序的三种基本结构:顺序结构,循环结构和分支结构
    • 循环是程序根据条件判断结果向后反复执行的一种运行方式,是一种程序的基本控制结构,条件循环和遍历循环结构都是基本的循环结构,死循环能够用于测试性能,形式上的死循环可以用break来退出,例如
    x = 10
    while True:
    	x = x -1
    	if x == 1:
    		break
    
    • p = -p #表示给p赋值为它的负数,Python中的=是赋值符号
    • 缩进表达层次关系,同时用来判断当前Python语句在分支结构
    • continue结束当次循环,但是不跳出循环
    • random库中用于生产随机小数的函数是random(),而randint()/getrandbits()/randrange()都产生随机整数
    • 程序错误是一个大的概念,不仅指代码运行错误,更代表功能逻辑错误。使用异常处理try-excepy,可以对程序的异常进行捕捉和处理,程序运行可能不会出错,但逻辑上可能会出错

    编程测试:

    • 四位玫瑰数:四位玫瑰数是4位数的自幂数。自幂数是指一个 n 位数,它的每个位上的数字的 n 次幂之和等于它本身‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬
      例如:当n为3时,有1^3 + 5^3 + 3^3 = 153,153即是n为3时的一个自幂数,3位数的自幂数被称为水仙花数‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‮‬‫
      请输出所有4位数的四位玫瑰数,按照从小到大顺序,每个数字一行
    #个人思路:求四位数的各个位数abcd
    for i in range(1000,10000):
        a = i%10
        b = (i//10)%10
        c = (i//100)%10
        d = (i//1000)%10
        if a**4 + b**4 + c**4 + d**4 == i:
            print(i)
    #参考答案:字符串+eval()
    s = ""
    for i in range(1000, 10000):
        t = str(i)
        if pow(eval(t[0]),4) + pow(eval(t[1]),4) + pow(eval(t[2]),4) + pow(eval(t[3]),4) == i :
            print(i)
    
    • 100以内素数之和:求100以内所有素数之和并输出‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      素数指从大于1,且仅能被1和自己整除的整数‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬,提示:可以逐一判断100以内每个数是否为素数,然后求和
    sum = 0
    for i in range(2,100):
        isFlag = 1 #判断是否为素数
        for j in range(2,i): #遍历2-i-1,看是否能被i整除
            if i%j == 0: #被整除说明不是素数
                isFlag = 0
                break
        if isFlag == 1:
            sum += i
    print(sum)
    #参考答案:将判断是否为素数封装为一个函数,倾向于这种解题思路
    def is_prime(n):
        for i in range(2,n):
            if n%i == 0:
                return False
        return True
    sum = 0
    for i in range(2,100):
        if is_prime(i):
            sum += i
    print(sum)
    

    测验5:函数和代码复用

    知识点概要:

    • 函数作用:增强代码可读性、降低编程复杂度、复用代码,函数不能直接提高代码的执行速度
    • 全局变量与局部变量:函数的参数一般为局部变量,函数内使用global s 表示变量s为全局变量
    • 函数调用前必须已经存在函数定义,否则无法执行,Python内置函数直接使用,不需要引用任何模块
    • 模块内高耦合,模块间低耦合:高耦合的特点是复用较为困难,模块间关系应尽可能简单,模块之间耦合度低,尽可能合理划分功能块,功能块内部耦合度高
    • 递归不会提高程序的执行效率,任何递归程序都可以通过堆栈或队列变为非递归程序
    • 函数是一段具有特定功能的、可重用的语句组,可以看做是一段具有名字的程序,通过函数名来调用,同时不需要知道函数的内部实现原理,只需要知道调用方法(接口)即可
    • def func(*a,b):是错误的函数定义,*a表示可变参数,可变参数只能放在函数参数的最后,即def func(a,*b):
    • 函数可以包含0个或多个return语句
    • 每个递归函数至少存在一个基例,但可能存在多个基例,基例表示不再进行递归,同时决定了递归的深度

    编程测试:

    • 随机密码生成:以整数17为随机数种子,获取用户输入整数N为长度,产生3个长度为N位的密码,密码的每位是一个数字。每个密码单独一行输出,产生密码采用random.randint()函数
    import random
    def genpwd(length):
        a = 10**(length-1)
        b = 10**length - 1
        return "{}".format(random.randint(a, b))
    length = eval(input())
    random.seed(17)
    for i in range(3):
        print(genpwd(length))
    
    #思路类似,同样过了
    def genpwd(length):
        high = 10**length
        low = 10**(length-1)
        return random.randrange(low,high)
    
    • 连续质数计算:获得用户输入数字N,计算并输出从N开始的5个质数,单行输出,质数间用逗号,分割。
      注意:需要考虑用户输入的数字N可能是浮点数,应对输入取整数;最后一个输出后不用逗号
    def prime(m): #判断是否为质数
        for i in range(2,m):
            if m%i == 0:
                return False
        return True
        
    n = eval(input())
    if n != int(n): #考虑输入为浮点数的情况
        n = int(n) + 1
    else:
        n = int(n)   
        
    times = 0 #统计质数的次数
    res = [] #存放输出结果
    while times < 5:
        if prime(n):
            res.append(n)
            times += 1
        n += 1
    for i in res[:len(res)-1]:
        print(i,end=",")
    print(res[-1]) #最后一个不输出逗号
    
    #参考答案
    def prime(m):
        for i in range(2,m):
            if m % i == 0:
                return False
        return True
    #需要对输入小数情况进行判断,获取超过该输入的最小整数(这里没用floor()函数)
    n = eval(input())
    n_ = int(n)
    n_ = n_+1 if n_ < n else n_
    count = 5
    #对输出格式进行判断,最后一个输出后不增加逗号(这里没用.join()方法)
    while count > 0:
        if prime(n_):
            if count > 1:
                print(n_, end=",")
            else:
                print(n_, end="")
            count -= 1 
        n_ += 1
    

    测验6:组合数据类型

    知识点概要:

    • 列表ls,ls.append(x)表示只能向列表最后增加一个元素,如果x是一个列表,则该列表作为一个元素增加到ls中
    • 集合“交并差补”四种运算分别对应的运算符是:& | - ^
    • 字典d,d.values()返回的是dict_values类型,包括字典中的所有值,通常与for…in组合使用
    • Python的元组类型:元组采用逗号和圆括号(可选)来表示,一旦创建就不能修改,一个元组可以作为另一个元祖的元素,可用多级索引获取信息,序列类型(元组、列表)中的元素都可以是不同类型
    • 创建字典时,如果相同键对应不同值,字典采用最后一个"键值对"
    d= {'a': 1, 'b': 2, 'b': '3'}
    print(d['b'])
    #输出结果:3
    
    • 集合与字典类型最外侧都用{}表示,不同在于集合类型元素是普通元素,字典类型元素是键值对。字典在程序设计中非常常用,因此直接采用{}默认生成一个空字典
    • 对于字典d:x in d表示判断x是否是字典d中的键,键是值的序号,也是字典中值的索引方式
    • Python序列类型有:列表类型、元组类型、字符串类型(Python内置数据类型中没有数组类型)
    • 组合数据类型能够将多个相同类型或不同类型的数据组织起来,通过单一的表示使数据操作更有序、更容易
    • 组合数据类型可以分为3类:序列类型、集合类型和映射类型;
    • Python的字符串元组列表类型都属于序列类型,序列类型总体上可以看成一维向量,如果其元素都是序列,则可被当作二维向量
    • 对于序列s:s.index(x)返回序列s中元素x第一次出现的序号,并不返回全部序号

    编程测试:

    • 数字不同数之和:获得用户输入的一个整数N,输出N中所出现不同数字的和‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      例如:用户输入 123123123,其中所出现的不同数字为:1、2、3,这几个数字和为6
    #参考答案:字符串可以通过list()直接变成列表,或通过set()直接变成集合
    n = input()
    ss = set(n)
    s = 0
    for i in ss:
        s += eval(i)
        #s += int(i) #同样可以
    print(s)
    
    • 人名最多数统计:给出了一个字符串,其中包含了含有重复的人名,请直接输出出现最多的人名
    #先使用字典建立"姓名与出现次数"的关系,然后找出现次数最多数对应的姓名
    s = '''双儿 洪七公 赵敏 赵敏 逍遥子 鳌拜 殷天正 金轮法王 乔峰 杨过 洪七公 郭靖 
           杨逍 鳌拜 殷天正 段誉 杨逍 慕容复 阿紫 慕容复 郭芙 乔峰 令狐冲 郭芙 
           金轮法王 小龙女 杨过 慕容复 梅超风 李莫愁 洪七公 张无忌 梅超风 杨逍 
           鳌拜 岳不群 黄药师 黄蓉 段誉 金轮法王 忽必烈 忽必烈 张三丰 乔峰 乔峰 
           阿紫 乔峰 金轮法王 袁冠南 张无忌 郭襄 黄蓉 李莫愁 赵敏 赵敏 郭芙 张三丰 
           乔峰 赵敏 梅超风 双儿 鳌拜 陈家洛 袁冠南 郭芙 郭芙 杨逍 赵敏 金轮法王 
           忽必烈 慕容复 张三丰 赵敏 杨逍 令狐冲 黄药师 袁冠南 杨逍 完颜洪烈 殷天正 
           李莫愁 阿紫 逍遥子 乔峰 逍遥子 完颜洪烈 郭芙 杨逍 张无忌 杨过 慕容复 
           逍遥子 虚竹 双儿 乔峰 郭芙 黄蓉 李莫愁 陈家洛 杨过 忽必烈 鳌拜 王语嫣 
           洪七公 韦小宝 阿朱 梅超风 段誉 岳灵珊 完颜洪烈 乔峰 段誉 杨过 杨过 慕容复 
           黄蓉 杨过 阿紫 杨逍 张三丰 张三丰 赵敏 张三丰 杨逍 黄蓉 金轮法王 郭襄 
           张三丰 令狐冲 赵敏 郭芙 韦小宝 黄药师 阿紫 韦小宝 金轮法王 杨逍 令狐冲 阿紫 
           洪七公 袁冠南 双儿 郭靖 鳌拜 谢逊 阿紫 郭襄 梅超风 张无忌 段誉 忽必烈 
           完颜洪烈 双儿 逍遥子 谢逊 完颜洪烈 殷天正 金轮法王 张三丰 双儿 郭襄 阿朱 
           郭襄 双儿 李莫愁 郭襄 忽必烈 金轮法王 张无忌 鳌拜 忽必烈 郭襄 令狐冲 
           谢逊 梅超风 殷天正 段誉 袁冠南 张三丰 王语嫣 阿紫 谢逊 杨过 郭靖 黄蓉 
           双儿 灭绝师太 段誉 张无忌 陈家洛 黄蓉 鳌拜 黄药师 逍遥子 忽必烈 赵敏 
           逍遥子 完颜洪烈 金轮法王 双儿 鳌拜 洪七公 郭芙 郭襄 赵敏'''
           
    names = s.split()
    d = {}
    for name in names:
        d[name] = d.get(name, 0) + 1
    Maxkey = ""
    MaxValue = 0
    for k in d:
        if d[k] > MaxValue:
            Maxkey = k
            MaxValue = d[k]
    print(Maxkey)
    #参考答案
    ls = s.split()
    d = {}
    for i in ls:
        d[i] = d.get(i, 0) + 1
    max_name, max_cnt = "", 0
    for k in d:
        if d[k] > max_cnt:
            max_name, max_cnt = k, d[k]
    print(max_name)
    

    测验7:文件和数据格式化

    知识点概要:

    • 数据组织纬度一维数据采用线性方式组织,对应于数学中的数组和集合等概念;二维数据采用表格方式组织,对应于数学中的矩阵;高维数据由键值对类型的数据构成,采用对象方式组织,字典就用来表示高维数据,一般不用来表示一二纬数据
    • Python对文件操作采用的统一步骤是:打开-操作-关闭(其中关闭可以省略)
    • CSV文件格式是一种通用的、相对简单的文件格式,应用于程序之间转移表格数据,CSV文件的每一行是一维数据,可以使用Python中的列表类型表示,整个CSV文件是一个二维数据,一般来说,CSV文件都是文本文件,由相同的编码字符组成
    • 二维列表切片ls = [[1,2,3],[4,5,6],[7,8,9]]获取其中的元素5要使用:ls[1][1]
    • 文件可以包含任何内容,是数据的集合和抽象,是存储在辅助存储器上的数据序列,而函数或类才是程序的集合和抽象
    • 打开文件后采用close()关闭文件是一个好习惯。如果不调用close(),当前Python程序完全运行退出时,该文件引用被释放,即程序退出时,相当于调用了close(),默认关闭
    • Python文件的"+"打开模式,与r/w/a/x一同使用,在原功能基础上同时增加了读写功能,同时赋予文件的读写权限
    • 同一个文件既可以用文本方式打卡,也可以用二进制方式打开
    • 列表元素如果都是列表,其可能表示二维数据,如[[1,2],[3,4],[5,6]],如果列表元素不都是列表,则它表示一维数据
    • Python文件读操作有:read()、readline()、readlines(),没有readtext()方法

    编程测试:

    • 文本的平均列数:打印输出附件文件的平均列数,计算方法如下:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      (1)有效行指包含至少一个字符的行,不计算空行‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      (2)每行的列数为其有效字符数‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬
      (3)平均列数为有效行的列数平均值,采用四舍五入方式取整数进位
    #for line in f 获取的line包含每行最后的换行符(\n),所以去掉该换行符再进行统计
    f = open("latex.log", "r", encoding="utf-8")
    lines = 0
    columns = 0
    for line in f:
        line = line.strip("\n")
        if len(line):
            lines += 1
            columns += len(line)
    print("{:.0f}".format(columns/lines))
    f.close()
    
    #参考答案如下:
    f = open("latex.log")
    s, c = 0, 0
    for line in f:
        line = line.strip("\n")
        if line == "":
            continue
        s += len(line)
        c += 1
    print(round(s/c))
    

    -CSV格式清洗与转换:附件是一个CSV格式文件,提取数据进行如下格式转换:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
    (1)按行进行倒序排列‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮
    (2)每行数据倒序排列‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
    (3)使用分号(;)代替逗号(,)分割数据,无空格‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
    按照上述要求转换后将数据输出

    f = open("data.csv", "r", encoding="utf-8")
    txt = f.readlines()
    txt.reverse() #按行进行倒序排列
    for line in txt:
        #line = line.strip("\n") #去除末尾换行符
        #line = line.replace(" ","") #去空格
        line = line.strip("\n").replace(" ", "")
        #ls = line.split(",") 
        #ls = ls[::-1]
        ls = line.split(",")[::-1] #逗号分隔并将分隔后的元素倒序
        print(";".join(ls)) #元素间插入分号
    f.close()
    
    #参考答案(使用strip()方法去掉每行最后的回车,使用replace()去掉每行元素两侧的空格)
    f = open("data.csv")
    ls = f.readlines()
    ls = ls[::-1]
    lt = []
    for item in ls:
        item = item.strip("\n")
        item = item.replace(" ", "")
        lt = item.split(",")
        lt = lt[::-1]
        print(";".join(lt))
    f.close()
    

    测验8:程序设计方法学

    知识点概要:

    • 用户体验:编程只是手段,程序最终为人类服务,用户体验很重要,一个提醒进度的进度条、一个永不抛出异常的程序、一个快速的响应、一个漂亮的图标、一个合适尺寸的界面等都是用户体验的组成部分。总的来说,用户体验是一切能够提升程序用户感受的组成
    • 计算思维是基于计算机的思维模式,计算机出现之前,由于没有快速计算装置,计算所反映的思维模式主要是数学思维,即通过公式来求解问题。当快速计算装置出现后,计算思维才真正形成
    • 软件产品 = 程序功能 + 用户体验 ;产品不仅需要功能,更需要更好的用户体验。往往,产品都需要综合考虑技术功能和人文设计,这源于产品的商业特性。即,商业竞争要求产品不能只关心技术功能,更要关心用户易用和喜好需求
    • os库os.system()可以启动进程执行程序
    • 函数自顶向下设计的关键元素,通过定义函数及其参数逐层开展程序设计
    • os.path子库os.path.relpath(path)用来计算相对路径
    • Python第三方库安装:使用pip命令、使用集成安装工具或访问UCI网站下载安装文件,请不要直接联系作者索要第三方库
    • 计算思维的本质是:抽象自动化
    • os库是Python重要的标准库之一,提供了路径操作、进程管理等几百个函数功能,覆盖与操作系统、文件操作等相关的众多功能;os库适合所有操作系统
    • 计算生态以竞争发展、相互依存和迅速更迭为特点,在开源项目间不存在顶层设计,以类自然界"适者生存"的方式形成技术演进路径

    编程测试:

    • 英文字符的鲁棒输入:获得用户的任何可能输入,将其中的英文字符进行打印输出,程序不出现错误
    inputStr = input()
    for i in inputStr:
        if i.islower() or i.isupper():
            print(i,end="")
         
    #参考答案:采用遍历字符的方式实现,通过约束字母表达到鲁棒效果
    alpha = []
    for i in range(26):
        alpha.append(chr(ord('a') + i))
        alpha.append(chr(ord('A') + i))
    s = input()
    for c in s:
        if c in alpha:
            print(c, end="")
    
    • 数字的鲁棒输入:获得用户输入的一个数字,可能是浮点数或复数,如果是整数仅接收十进制形式,且只能是数字。对输入数字进行平方运算,输出结果,要求:
      1)无论用户输入何种内容,程序无错误‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬
      2)如果输入有误,请输出"输入有误"
    number = input()
    try:
        #complex()和complex(eval())之间的比较
        #将能够排除非数字类型的输入
        if complex(number) == complex(eval(number)):
            print(eval(number) ** 2)
    except:
        print("输入有误") 
        
    '''
    不能直接使用eval(),否则用户可以通过输入表达式(如100**2)输入数字
    与要求不同(在实际应用中会带来安全隐患)
    '''
    

    测验9:Python计算生态纵览

    知识点概要:

    • Python网络爬虫方向第三方库有:Requests、Scrapy、pyspider
    • Python数据可视化方向第三方库有:Mayavi、Matplotlib、Seaborn
    • Python Web信息提取方向第三方库有:Beautiful Soup、Python-Goose、Re
    • Python游戏开发第三方库有:Panda3D、cocos2d、PyGame
    • Python数据分析方向第三方库有:Numpy、Pandas、Scipy
    • Python图形用户界面方向(GUI)第三方库有:PyQt5、wxPython、PyGObject
    • Python网站开发框架方向第三方库有:Django、Pyramid、Flask
    • Python文本处理方向第三方库有:NLTK、python-docx、PyPDF2
    • Python网络应用开发方向第三方库有:aip、MyQR、WeRobot
    • aip是百度的人工智能功能Python访问接口
    • Python人工智能方向第三方库有:TensorFlow、Scikit-learn、MXNet
    • Vizard是虚拟现实第三方库
    • pyovr是增强现实开发库
    • redis-py是redis数据的Python访问接口

    编程测试:

    • 系统基本信息获取:获取系统的递归深度、当前执行文件路径、系统最大UNICODE编码值等3个信息,并打印输出;输出格式如下:‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬
      RECLIMIT:<深度>, EXEPATH:<文件路径>, UNICODE:<最大编码值>‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮
      提示:请在sys标准库中寻找上述功能
    import sys
    print("RECLIMIT:{}, EXEPATH:{}, UNICODE:{}".format(sys.getrecursionlimit(), sys.executable, sys.maxunicode))
    
    • 二维数据表格输出:tabulate能够对二维数据进行表格输出,是Python优秀的第三方计算生态。‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬编写程序,能够输出如下风格效果的表格数据
      输出效果
    data = [ ["北京理工大学", "985", 2000], \
             ["清华大学", "985", 3000], \
             ["大连理工大学", "985", 4000], \
             ["深圳大学", "211", 2000], \
             ["沈阳大学", "省本", 2000], \
        ]
    from tabulate import tabulate
    print(tabulate(data, tablefmt="grid"))
    

    期末测验

    *编程测试:

    • 无空隙回声输出:获得用户输入,去掉其中全部空格,将其他字符按收入顺序打印输出
    print(input().replace(" ",""))
    
    • 文件关键行数:关键行指一个文件中包含的不重复行。关键行数指一个文件中包含的不重复行的数量。‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬统计附件文件中关键行的数量
    f = open("latex.log", "r", encoding="utf-8")
    d = {}
    for line in f:
        d[line] = d.get(line, 0) + 1
    print("共{}关键行".format(len(d)))
    
    #参考答案:如果需要"去重"功能,请使用集合类型
    f = open("latex.log")
    ls = f.readlines()
    s = set(ls)
    print("共{}关键行".format(len(s)))
    
    • 剩余两题与测验九重复,不重复记录
    展开全文
  • 前端面试题(持续更新中)

    万次阅读 多人点赞 2019-11-06 17:16:33
    闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都 永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数本 2.数据类型 基本数据类型:String,Boolean,number,Null,...

    全家桶项目源码:Vue全家桶+SSR+Koa2全栈开发美团网[完整版] 链接:https://pan.baidu.com/s/1cwPDVkj_I5z568mYIHni4A 提取码:24g2

    2020字节跳动扎心面试题链接(从公众号获取的):
    https://mp.weixin.qq.com/s/B8xRPxwjJfURyYzTQgIxUw

    CSS面试题:
    1、谈谈你对CSS盒模型的认识?

    1、基本概念:标准模型+IE模型
    CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:内边距(padding),边框(border),margin(外边距),和内容(content)。
    标准盒模型:一个块的总宽度=width+margin(左右)+padding(左右)+border(左右)
    怪异(IE)盒模型:一个块的总宽度=width+margin(左右)(既width已经包含了padding和border值)
    设置盒模型:box-sizing:border-box

    2、CSS是如何设置这两种模型,那么二者怎么转化呢?

    content-box: 指的是W3C标准盒模型,也是默认的设置属性。
    border-box:指的是IE盒模型,width和height包含了padding和border。

    3、JS如何获取盒模型对应的宽和高?

    dom.style.width/height:对节点样式可读可写,但只能读或写内嵌的CSS样式对于在(style)或外联样式不能读写。
    dom.currentStyle.width/height:拿到的是渲染之后的宽和高,比较真实,但支持IE浏览器
    window.getComputedStyle(dom).width/height:方法是只读的,只能获取样式,不能设置。
    dom.getBoundingClientRect().width/height:getBoundingClientRect()方法得到8个值,除了 width 和 height 外的属性x、y、left、top、right和bottom都是相对于视口(viewport)的左上角位置而言的。

    4、什么是BFC?BFC的原理?

    块级格式化上下文。是一种边距重叠解决方案。
    应用场景: 1. 解决margin叠加的问题
    2. 用于布局(overflow: hidden)
    3.BFC不会与浮动盒子叠加。
    4. 用于清除浮动,计算BFC高度。

    5、行内元素和块级元素有什么区别?

    块级元素:显示在一块内,会自动换行,元素会从上到下垂直排列,各自占一行,块级元素可以设置宽高,如p,ul,form,div,(h1-h6)等标签元素
    行内元素:元素在一行内水平排列,高度由元素的内容决定,行内元素不可以设置宽高,如a,br,span,input等元素。

    6、行内元素和块级元素如何转换?

    行变块display:block
    块变行display:inline
    display:inline-block(可以在同一行内显示)

    7、什么是伪类选择器和伪元素?列举3个CSS3中引入的伪类选择器和伪元素!

    伪类用一个冒号来表示,而伪元素则用两个冒号来表示
    伪元素选择器:dom中不存在的元素,仅仅是css中用来渲染,添加一些特殊效果的,比如p::before,选择p标签(真元素)前面的假元素(伪元素,p标签前面没有元素,只是假设有)
    ::first-line选择元素的第一行,比如说改变每个段落的第一行文本的样式
    ::before::after这两个主要用来给元素的前面或后面插入内容,这两个常用"content"配合使用,见过最多的就是清除浮动
    ::selection用来改变浏览网页选中文的默认效果

    伪类选择器:一个概念上的类,不是我们定义的,是抽象的。如a:hover,选择a标签(元素选择器)中具有鼠标悬停类的所有元素,这个类是抽象的,不是我们自己定义的,再如first-child,选择第一个,选择具有这个类性质的所有元素,“第一个”,这个类就抽象了,我们没必要定义一个第一个这样的类
    列举::root()选择器,根选择器,匹配元素E所在文档的根元素。在HTML文档中,根元素始终是(html)。:root选择器等同于(html)元素。
    :not()选择器称为否定选择器,和jQuery中的:not选择器一模一样,可以选择除某个元素之外的所有元素。
    :empty()选择器表示的就是空。用来选择没有任何内容的元素,这里没有内容指的是一点内容都没有,哪怕是一个空格。

    8、px和em,rem的区别?

    px 实际上就是像素,用PX设置字体大小时,比较稳定和精确。px是固定长度单位,不随其它元素的变化而变化
    em 就是根据基准来缩放字体的大小。em 是相对长度单位。em是相对于父级元素的单位,会随父级元素的属性(font-size或其它属性)变化而变化
    rem是CSS3新增的一个相对单位,rem是相对于根目录(HTML元素)的,所有它会随HTML元素的属性(font-size)变化而变化
    例如: ==屏幕宽度/设计宽度 = 1rem的值/预设定rem的值。
    1920/1920=100/100 ;
    所以 1rem=1920/1920*100 ;
    document.documentElement 是html节点
    document.documentElement.style.fontSize = ((windowWidth / designWidth) * rem2px) + 'px';
    假如,用户将屏幕拖小了,变为960。1rem将自动变为50px;960/1920乘以100=50
    这里需要判断下,当屏幕的宽度大于设计稿定义的宽度,用设计稿的宽度,如果小于,用屏幕宽度作为变量屏幕宽度。

    10、关于绝对定位,相对定位和固定定位

    1、相对定位不脱离标准流,在页面中占位置 。
    相对于自己原来的位置来进行定位 。
    2、绝对定位脱离标准流,在页面中不占位置。
    如果没有父元素,则相对于body定位;如果有父元素,但父元素没有定位,那么还是相对于body定位;如果父元素有定位,那么相对于父元素来定位。
    3、固定定位:相对于浏览器窗口进行定位
    相对定位:position: relative;
    绝对定位:position: absolute;

    11、CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?

    CSS 选择符:
    1.id选择器( # myid)
    2.类选择器(.myclassname)
    3.标签选择器(div, h1, p)
    4.相邻选择器(h1 + p)
    5.子选择器(ul > li)
    6.后代选择器(li a)
    7.通配符选择器( * )
    8.属性选择器(a[rel = “external”])
    9.伪类选择器(a: hover, li:nth-child)

    1.2 可以继承的属性:
    可继承的样式: font-size font-family color, UL LI DL DD DT;
    不可继承的样式:border padding margin width height ;

    优先级: !important > id > class > tag
    important 比 内联优先级高,但内联比 id 要高

    CSS3新增伪类举例:
    p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。
    p:last-of-type 选择属于其父元素的最后 <p> 元素的每个<p> 元素。
    p:only-of-type 选择属于其父元素唯一的<p> 元素的每个<p> 元素。
    p:only-child 选择属于其父元素的唯一子元素的每个<p> 元素。
    p:nth-child(2) 选择属于其父元素的第二个子元素的每个<p> 元素。
    :enabled :disabled 控制表单控件的禁用状态。
    :checked 单选框或复选框被选中。

    12、以下是CSS3的几种常用前缀

    -webkit
    -moz
    -ms
    -o

    13、CSS3新增的伪类有哪些

    p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。
    p:only-of-type 选择属于其父元素唯一的<p> 元素的每个 <p> 元素。
    p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。
    p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。
    :enabled、:disabled 控制表单控件的禁用状态。
    p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。
    :checked,单选框或复选框被选中。

    14、CSS3有哪些新特性?

    1. CSS3实现圆角(border-radius),阴影(box-shadow)
    2. 对文字加特效(text-shadow),线性渐变(gradient),旋转(transform)
    3. transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);// 旋转,缩放,定位,倾斜
    4. 增加了更多的CSS选择器 多背景 rgba
    5. 在CSS3中唯一引入的伪类是 ::selection.
    6. 媒体查询,多栏布局
    7. border-image

    15、为什么要初始化CSS样式。

    因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。当然,初始化样式会对SEO有一定的影响,但求影响最小的情况下初始化。

    16、解释下浮动和它的工作原理?清除浮动的技巧

    由于浮动元素不再占用原文档流的位置,所以它会对后面的元素排版产生影响,清除浮动的本质:主要为了解决父级元素因为子级浮动引起内部高度为0的问题。

    1. 使用空标签清除浮动。
      这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。
    2. 使用overflow。
      给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。
    3. 使用after伪对象清除浮动。
      该方法只适用于非IE浏览器。
      一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;
      可以给父元素设置overflow:auto或者hidden

    #JS的面试问题:
    0、如何判断一个变量是对象还是数组?

    1、我们能够使用typeof判断变量的身份,判断字符串得到string,数字和NaN得到number,函数会得到function等,但是判断数组,对象和null时都会得到object,这就是typeof的局限性,
    2、使用instanceof(比较运算符)可以用来判断一个变量是数组还是对象
    3、constructor(构造函数)
    4、Object.prototype.toString.call()
    总结:判断简单数据类型可以用typeof,判断数组,对象使用instanceofconstructorObject.prototype.toString.call(),最好使用Object.prototype.toString.call(),更加精准

    1.闭包

    闭包就是能够读取其他函数内部变量的函数。
    外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象
    创建闭包最常见方式,就是在一个函数内部创建另一个函数。
    闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都永远不会被释放
    在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;

    2.数据类型

    基本数据类型:String( 字符串),Boolean(布尔),number(数值),Null(空值),undefined(未定义)
    引用数据类型:Object(Array,Date,RegExp,Function)

    3.javascript 中 == 和 === 的区别是什么?举例说明。

    ===会自动进行类型转换,==不会

    4.请尽可能详尽的解释 ajax 的工作原理

    思路:先解释异步,再解释 ajax 如何使用
    Ajax 的原理简单来说通过 XmlHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后用JS来操作DOM而更新页面。XMLHttpRequest 是 ajax 的核心机制,它是在 IE5 中首先引入的,是一种支持异步请求的技术。简单的说,也就是 javascript 可以及时向服务器提出请求和处理响应,而不阻塞用户。达到无刷新的效果。
    特点:Ajax 可以实现异步通信效果,实现页面局部刷新,带来更好的用户体验;按需获取数据,节约带宽资源

    ajax是什么?

    1. 通过异步模式,提升了用户体验
    2. 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
    3. Ajax 在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。

    Ajax 的缺点:

    1. Ajax 不支持浏览器 back 按钮
    2. 安全问题 Ajax 暴露了与服务器交互的细节
    3. 对搜索引擎的支持比较弱
    4. 破坏了程序的异常机制
    5. 不容易调试

    HTTP协议类型题目:
    5. HTTP 状态消息

    200:请求已成功,请求所希望的响应头或数据体将随此响应返回。
    302:请求的资源临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当
    继续向原有地址发送以后的请求。只有在Cache-Control或 Expires中进行了指定的情况下,
    这个响应才是可缓存的
    304:如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上
    次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304 响应禁
    止包含消息体,因此始终以消息头后的第一个空行结尾。
    403:服务器已经理解请求,但是拒绝执行它。
    404:请求失败,请求所希望得到的资源未被在服务器上发现。
    500:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。

    6.说一下什么是Http协议

    对客户端和服务器端之间数据传输的格式规范,格式简称为“超文本传输协议”

    7.什么是Http协议无状态协议?怎么解决Http协议无状态协议?

    (1)、无状态协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息
    (2)、无状态协议解决办法: 通过1、Cookie 2、通过Session会话保存。

    8.Http协议中有哪些请求方式?

    GET:用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器,从指定的资源请求数据
    POST:用于传输信息给服务器, 向指定的资源提交要处理的数据
    PUT:传输文件,报文主体中包含文件内容,保存到对应URI位置
    HEAD:获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效
    DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件
    OPTIONS:查询响应URI支持的HTTP方法

    区别:

    Get 是通过地址栏来传值,而 Post 是通过提交表单来传值。

    在这里插入图片描述

    9.Http协议由什么组成?

    请求报文包括三部分:
    (1).请求行:包含请求方法,URI,HTTP版本协议 (2).请求首部字段 (3).请求内容实体
    响应报文包含三部分:
    (1).状态行:包含HTTP版本,状态码,状态码原因短语 (2).响应首部字段 (3).响应内容实体

    10.HTTP协议的工作原理?

    HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息,通常情况下会配合数字证书实现。

    13.ajax的同步和异步区别:

    1. 同步:提交请求 -> 等待服务器处理 -> 处理完毕返回,这个期间客户端浏览器不能干任何事
    2. 异步:请求通过事件触发 -> 服务器处理(这是浏览器仍然可以作其他事情)-> 处理完毕
      ajax.open方法中,第3个参数是设同步或者异步。

    14.跨域? ?

    理解跨域的概念:协议、域名、端口都相同才同域,否则都是跨域

    14-1、什么情况下会碰到跨域问题?有哪些解决方法?

    跨域是指a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,或是a页面为ip地址,b页面为域名地址,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。
    解决方法:1. JSONP方法:JSONP是服务器与客户端跨源通信的常用方法,Jsonp 需要目标服务器配合一个callback函数网页通过添加一个(script)元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
    首先,网页动态插入(script)元素,由它向跨源网址发出请求。
    2.通过修改document.domain来跨子域
    3.使用window.name来进行跨域
    4.通过CORS解决AJAX跨域

    15.简述 ajax 的过程。

    1. 创建 XMLHttpRequest 对象,也就是创建一个异步调用对象
    2. 创建一个新的 HTTP 请求,并指定该 HTTP 请求的方法、URL 及验证信息
    3. 设置响应 HTTP 请求状态变化的函数
    4. 发送 HTTP 请求
    5. 获取异步调用返回的数据
    6. 使用 JavaScript 和 DOM 实现局部刷新

    16.axios和ajax的区别

    axios是通过promise实现对ajax技术的一种封装,就像jQuery实现ajax封装一样。
    简单来说: ajax技术实现了网页的局部数据刷新,axios实现了对ajax的封装。

    ②axios特征:
    1.自动转换JSON数据
    2.从 node.js 创建 http 请求
    3.支持 Promise API
    4.客户端支持防止CSRF
    5.提供了一些并发请求的接口
    PS:防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key,根据浏览器同源策略,假冒的网站是拿不到你cookie中得到key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略

    17.JavaScript 链 原型,原型链 ? 有什么特点?

    1.原型对象也是普通的对象,是对象一个自带隐式的 _ proto_ 属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null 的话,我们就称之为原型链
    2. 原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。

    3.每一次获取对象中的属性都是一次查询过程,如果在自有属性中找不到就会去原型对象中查找,如果原型对象中还查不到,就回去原型对象的原型中查找,也就是按照原型链查找,直到查找到原型链的顶端,也就是Object的原型。

    作用域链:
      一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值。
      但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。

    一、作用域
      在 Javascript 中,作用域分为 全局作用域 和 函数作用域
      全局作用域:
        代码在程序的任何地方都能被访问,window 对象的内置属性都拥有全局作用域。
      函数作用域:
        在固定的代码片段才能被访问

    18、JS创建对象有几种方法?

    1.new Object()
    2.使用字面量
    3.工厂模式
    4.构造函数模式(constructor)
    5.原型模式(prototype)
    6.构造函数+原型模式
    还是点击下面链接讲解的比较详细吧 ↓
    https://www.jianshu.com/p/1fb0447db852
    在这里插入图片描述

    19、虚拟dom和实体dom的区别?

    DOM的本质:
    浏览器概念,浏览器从服务器端读取html页面,浏览器将html解析成一棵元素嵌套关系的dom树,用对象来表示页面上的元素,并提供操作dom对象的api。
    虚拟DOM:
    框架概念,程序员用js对象来模拟页面上dom元素的嵌套关系( 本质 ),为了实现页面元素的高效更新( 目的 )
    区别:1、虚拟DOM不会进行重排与重绘操作;
    2、虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要修改的部分,最后进行重排和重绘,减少过多DOM节点重排和重绘损耗。
    3、虚拟DOM有效降低大面积(真实DOM节点)的重排和重绘,因为最终与真实DOM比较差异,可以局部渲染

    20、描述一下事件冒泡机制

    当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。

    21、请描述一下cookies,sessionStorage和localStorage的区别

    cookie(储存在用户本地终端上的数据)是网站为了标识用户身份而储存在用户本地终端上的数据,cookie数据始终在同源的http请求中携带,只会在浏览器和服务器间来回传递。另外两个不会自动把数据发给服务器,仅在本地保存。
    在这里插入图片描述

    22、js阻止事件冒泡的两种方法

    event.stopPropagation( )
    event.target

    23、JS的内置对象
    在这里插入图片描述
    24、函数调用的四种方式

    函数调用模式
    方法调用模式
    构造器调用模式
    间接调用模式,通过call()和apply()进行

    25、JS中常见的几种继承方法

    1.原型链继承
    原型链实现继承的思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。
    原型链的基本概念: 当一个原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个指向另一个原型的指针。同时,另一个原型中也包含着一个指向另一个构造函数的指针。如果另一个原型是另一个类型的实例,此时实例和原型就构成了原型链
    原型链存在的问题
    1)包含引用类型值的原型属性会被所有实例共享,这会导致对一个实例的修改会影响另一个实例。在通过原型来实现继承时,原型实际上会变成另一个类型的实例。原先的实例属性就变成了现在的原型属性
    2)在创建子类型的实例时,不能向超类型的构造函数中传递参数

    2.构造函数继承(经典继承)
    借用构造函数的基本思想,即在子类型构造函数的内部调用超类型构造函数。函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法可以在新创建的对象上执行构造函数
    借用构造函数的优势:可以在子类型构造函数中向超类型构造函数传递参数
    借用构造函数的问题:
    1)无法避免构造函数模式存在的问题,方法都在构造函数中定义,因此无法复用函数。
    2)在超类型的原型中定义的方法,对子类型而言是不可见的。因此这种技术很少单独使用。

    3.组合方式继承(构造函数 + 原型链)
    组合继承:指的是将原型链和借用构造函数的技术组合到一起。思路是使用原型链实现对原型方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数的复用,又能够保证每个实例都有它自己的属性。
    组合继承的优势
    避免了原型链和借用构造函数的缺点,融合了他们的优点,是JavaScript中最常用的继承模式。instanceof和isprototypeOf()也能够用于识别基于组合继承创建的对象

    4.es6方法继承

    27、JS运行机制

    JS为什么是单线程?

    • JS的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。

    JS的运行机制:

    • 因为JavaScript是单线程,意味着任务要一个接着一个完成,但是,如果前一个任务执行时间很长,那么后面的任务就得一直阻塞着,这样用户体验十分差。
      JavaScript的设计者考虑到了这一点,所以他将JavaScript的任务分为两种,在主线程上执行的任务"同步任务",被主线程挂载起来的任务"异步任务",后者一般是放在一个叫任务队列的数据结构中。
      只有当所有同步任务都执行完了才会,开始观察任务队列中被挂载起来的任务,并且按照队列的特性,先进先出的依次执行。

    28、DOM是什么?

    DOM是Document Object Model,即文档对象模型,它允许脚本控制Web页面、窗口和文档。

    29、DOM事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

    事件捕获(event capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。
    事件冒泡(dubbed bubbling):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。
    无论是事件捕获还是事件冒泡,它们都有一个共同的行为,就是事件传播,
    dom标准事件流的触发的先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。

    30、数组去重的方法

    1.ES6 Set去重

    var arr = [1,2,3,3,2,1,5,1];
    var arr2 = Array.from(new Set(arr))
    console.log(arr2)
    
    var arr = [1,2,3,3,2,1,5,1];
    let a = [...new Set(arr)]
    console.log(a)
    

    2.利用for嵌套for,然后splice去重
    3.利用indexOf去重

    var arr = [1,3,4,5,6,7,4,3,2,4,5,6,7,3,2];
    function find(){
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
    if (newArr.indexOf(arr[i]) == -1 ) { //也可以换成if(newArr.indexOf(arr[i])<0)
    newArr.push(arr[i]);
      }
    }
    consoloe.log(newArr); // [1, 3, 4, 5, 6, 7, 2]
    }
    find(arr); //调用这个方法  indexOf对大小写敏感
    

    4.利用filter
    filter(x,index,self)可以为数组提供过滤功能,其中x代表元素,index是与X一同传入元素的索引,而self代表数组本身。

    var arr = [1, 2, 2, 3, 4, 5, 5, 6, 7, 7];
    var arr2 = arr.filter(function(x, index,self) {
    return self.indexOf(x)===index;
    }); 
    console.log(arr2); //[1, 2, 3, 4, 5, 6 ,7]
    

    32、事件委托

    简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
    举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
    好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。

    34、DOM操作——怎样添加、移除、移动、复制、创建和查找节点。

    在这里插入图片描述

    35、null和undefined的区别?

    null是一个表示"无"的对象,转为数值时为0
    undefined是一个表示"无"的原始值,转为数值时为NaN
    当声明的变量还未被初始化时,变量的默认值为undefined
    null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象
    undefined表示 “缺少值”,就是此处应该有一个值,但是还没有定义。典型用法是:

    • 1.变量被声明了,但没有赋值时,就等于 undefined
      2. 调用函数时,应该提供的参数没有提供,该参数等于 undefined
      3. 对象没有赋值的属性,该属性的值为 undefined
      4. 函数没有返回值时,默认返回 undefined
    • null表示“没有对象”,即该处不应该有值。典型用法是:
      1. 作为函数的参数,表示该函数的参数不是对象
      2. 作为对象原型链的终点

    36、哪些操作会造成内存泄漏?

    内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
    垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。

    • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏。
    1. 闭包
    2. 控制台日志
    3. 循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

    37、typeof null返回什么?为什么?

    不同的对象在底层都表示为二进制,在javascript中二进制前三位都为0的话会被判断为object类型,
    null的二进制表示全0,自然前三位也是0,所以执行typeof时会返回“object”

    39、ES6中…运算符能做什么

    1.复制数组 2.合并数组 3. 扩展运算符可以与解构赋值结合起来,用于生成数组。 4.扩展运算符还可以将字符串转为真正的数组

    42、如何实现浏览器内多个标签页之间的通信?

    第一种——调用localStorage
    在一个标签页里面使用 localStorage.setItem(key,value)添加(修改、删除)内容;
    在另一个标签页里面监听 storage 事件。
    即可得到 localstorge 存储的值,实现不同标签页之间的通信。

    第二种——调用cookie+setInterval()
    将要传递的信息存储在cookie中,每隔一定时间读取cookie信息,即可随时获取要传递的信息。

    43、数据类型的自动转换和隐式转换你知道哪些?

    隐式类型转换:
    1 == ‘1’
    ‘1’ + 1
    ‘1’ - 1
    显示类型转换
    parseInt(str,radix)/parseFloat(str,radix)/Number()转变成数字。
    Boolean(param)转变成布尔值
    subString()转变成字符串

    VUE方面的问题:
    1.谈谈你对MVVM开发模式的理解

    Vue是一个 MVVM框架,其各层的对应关系如下:
    View层:在Vue中是绑定dom对象的HTML(代表UI视图,负责数据的展示;)
    ViewModel层:在Vue中是实例的vm对象 (负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;)
    Model层:在Vue中是data、computed、methods等中的数据(代表数据模型,数据和业务逻辑都在Model层中定义;)
    在 Model 层的数据变化时,View层会在ViewModel的作用下,实现自动更新

    2、Vue的响应式原理?

    Vue响应式底层实现方法是 Object.defineProperty() 方法,该方法中存在一个getter和setter的可选项,可以对属性值的获取和设置造成影响
    Vue中编写了一个wather来处理数据,在使用getter方法时,总会通知wather实例对view层渲染页面,同样的,在使用setter方法时,总会在变更值的同时,通知wather实例对view层进行更新

    3、Vue的生命周期

    1.beforeCreate --创建前
    触发的行为:vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。
    在此阶段可以做的事情:加loading事件
    2.created --创建后
    触发的行为:vue实例的数据对象data有了,$el还没有
    在此阶段可以做的事情:解决loading,请求ajax数据为mounted渲染做准备
    3.beforeMount --渲染前
    触发的行为:vue实例的$el和data都初始化了,但还是虚拟的dom节点,具体的data.filter还未替换
    在此阶段可以做的事情:。。。
    4.mounted --渲染后
    触发的行为:vue实例挂载完成,data.filter成功渲染
    在此阶段可以做的事情:配合路由钩子使用
    5.beforeUpdate --更新前
    触发的行为:data更新时触发
    在此阶段可以做的事情:。。。
    6.updated —更新后
    触发的行为:data更新时触发
    在此阶段可以做的事情:数据更新时,做一些处理(此处也可以用watch进行观测)
    7.beforeDestroy —销毁前
    触发的行为:组件销毁时触发
    在此阶段可以做的事情:可向用户询问是否销毁
    8.destroyed —销毁后
    触发的行为:组件销毁时触发,vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在
    在此阶段可以做的事情:组件销毁时进行提示

    4、请详细说下你对vue生命周期的理解?

    答:总共分为8个阶段:创建前 / 后,载入前 / 后,更新前 / 后,销毁前 / 后。
    创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。
    载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
    更新前/后:当data变化时,会触发beforeUpdateupdated方法。
    销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

    5、vue生命周期在真实场景下的业务应用

    created: 进行ajax请求异步数据的获取、初始化数据
    mounted: 挂载元素内dom节点的获取
    nextTick: 针对单一事件更新数据后立即操作dom
    updated: 任何数据的更新,如果要做统一的业务逻辑处理
    watch: 监听具体数据变化,并做相应的处理

    7、Vue中双向数据绑定是如何实现的?

    Vue在组件和实例初始化的时候,会将data里的数据进行数据劫持(object.definepropty对数据做处理)。被解除过后的数据会有两个属性:一个叫getter,一个叫setter
    getter是使用数据的时候触发,setter是在修改数据的时候触发,修改数据的时候触发setter,同时也触发了底层的watcher(可以收到属性的变化通知并执行相应的函数,从而更新视图。)监听,通知dom修改刷新。

    8、父组件与子组件传值

    父向子传值:属性传值,父组件通过给子组件标签上定义属性,子组件通过props方法接收数据;
    子向父传值:事件传值,子组件通过$emit(‘自定义事件名’,值),父组件通过子组件上的@自定义事件名=“函数”接收 ($emit方法传递参数)

    10、 如何让css只在当前组件中起作用

    将当前组件的 (style)修改为(styple scoped)

    11、第一次加载页面会触发哪几个钩子

    第一次加载会触发 beforeCreatecreatedbeforeMountmounted四个钩子

    12、Vuex是什么?

    Vuex是专门为Vue服务,用于管理页面的数据状态、提供统一数据操作的生态系统
    vuex:是vue提供的状态管理工具,简单解释就是vue各个组件直接的变量是不能直接共享的,组件直接的参数传递才多层的时候变得异常复杂,所以就诞生了vuex的状态管理工具,保证了状态的统一和可追踪
    ①:这个状态自管理应用包含以下几个部分:
    state,驱动应用的数据源;
    view,以声明方式将 state 映射到视图;
    actions,响应在 view 上的用户输入导致的状态变化。
    ②:使用vuex管理数据的好处:
    能够在vuex中集中管理共享的数据,便于开发和后期进行维护
    能够高效的实现组件之间的数据共享,提高开发效率
    存储在vuex中的数据是响应式的,当数据放生改变时,页面中的数据会同步更新
    ③:vuex中的数据和data中的数据与什么区别?
    vuex中的数据是全局的,共享的,data中的数据是私有的
    vuex中的数据是响应式的,只要vuex中的数据发生改变,引用vuex中的数据的文件会同步更新
    vuex中的数据是单向的,想要修改vuex中的数据必须在mutation中修改

    13、router是什么?

    1.routerthis.$router 是路由【导航对象】,用它 可以方便的 使用 JS 代码,实现路由的 前进、后退、 跳转到新的 URL 地址
    2.routes:指创建vue-router路由实例的配置项。用来配置多个route路由对象
    3.routethis.$route 是路由【参数对象】,所有路由中的参数, params, query 都属于它

    14、vue单页面应用及优缺点

    vue核心是一个响应的数据绑定系统,mvvm,数据驱动,组件化,轻量,简洁,高效,快速,模块友好。
    缺点:不支持低版本浏览器,最低到IE9,不利于SEO的优化,首页加载时间较长,不可以使用浏览器的导航按钮需要自行实现前进后退。

    15、vue生命周期的作用是什么?

    它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

    16、vue.nextTick()的用处?

    nextTick可以使我们在下次DOM更新循环结束之后执行延迟回调,用于获得更新后的DOM。

    18、兄弟组件之间如何传值?

    可以用过一个vue实例Bus作为媒介,要相互通信的兄弟组件之中,都引入Bus,之后通过分别调用Bus事件触发 e m i t 和 监 听 emit和监听 emiton来实现组件之间的通信和参数传递,类似window的全局自定义事件。类似与子传父,只不过是利用一个新的vue示例作为媒介,而不是当前vue示例(this)

    19、jquery和vue的控制DOM元素的主要区别是什么?

    jquery操作的是直接dom元素。vue操作的是dom元素对象。
    vue.js优势是(视图-模型)双向绑定,简化了dom的操作(不用重写大量的html标签),提高dom的复用率(以最少代码实现更多的功能),倾向于数据读写,虽然看上去使用比较繁琐,但是利于后期的维护。
    jquery优势是jquery语义化,容易理解,比较简单,可拓展的插件多。
    总结:如果dom操作频繁,不需要动画效果,就使用vue.js。如果dom操作不频繁,但又需要复杂的动画效果,就使用jquery. vue.js比较适合于后台管理页面,jquery比较适合于前台用户交互页面。

    20、vue2模版template的四种写法?

    1.写在构造器里的:
    2.写在(template)标签里
    3.写在(script type=“x-template”)标签里
    在这里插入图片描述

    21、var let const声明的变量的区别

    let不允许在相同作用域内,重复声明同一个变量。let声明的变量只在其所在代码块内有效
    const是定义常量的,而且定义一次以后不能再进行更改, 否者会报错;
    使用const定义的常量, 拥有let一样的特性(无声明提前, 有块状作用域, 重复声明)

    • let:* 声明的变量只在它所在的代码块有效; * 需要先声明然后再使用,否则报错
    • var:* 声明的变量在全局范围内都有效;
    • var定义的变量可以修改,如果不初始化会输出undefined,不会报错
    • const: * 声明一个只读的常量,一旦声明,常量的值就不允许改变;
    • 一旦声明了变量,就必须初始化,不能留到以后赋值;
    • 只在声明所在的块级作用域内有效;
      在这里插入图片描述

    22、如何理解JSON?

    JSON是一种轻量级的数据交换格式,作用:通常用于服务端向页面传输数据。
    JSON 是 一个 JS 对象,有 2 个 API
    JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
    JSON.parse() 方法用于将一个 JSON 字符串转换为对象。

    23、函数声明和函数表达式的区别(作用域)

    1.以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的.
    2.以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用.
    3.以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而函数表达式可以在任何地方声明.

    24、关于动态路由

    不能传递参数的是静态路由,可以传递参数,但是其对应的路由数量是不确定的,叫动态路由
    在参数名前面加上:,然后将参数写在路由的path内
    这是无参数跳转在这里插入图片描述

    query和params两者都可以传递参数,区别是什么?
    1.query 传参配置的是path,而params传参配置的是name,在params中配置path无效
    2.query在路由配置不需要设置参数,而params必须设置
    3.query传递的参数会显示在地址栏中
    4.params传参刷新会无效,但是query会保存传递过来的值,刷新不变

    25、vue是什么?跟JS有什么区别?

    vue就是一个js库,并且无依赖别的js库,跟jquery差不多。vue的核心库只关注视图层,非常容易与其它库或已有项目整合。Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。
    区别:在传统web开发中,我们搭建项目都以html结构为基础,然后通过jquery或者js来添加各种特效功能,需要去选中每一个元素进行命令,这样太繁琐了
    vue的好处:1.数据绑定:vue会根据对应的元素,进行设置元素数据,通过输入框,以及get获取数据等多种方式进行数据的实时绑定,进行网页及应用的数据渲染 。
    2.组件式开发:通过vue的模块封装,它可以将一个web开发中设计的各种模块进行拆分,变成单独的组件,然后通过数据绑定,调用对应模版组件,同时传入参数,即可完成对整个项目的开发。
    一句话概括:用数据绑定的思想,vue可以简单写单个页面,也可以写一个大的前端系统,也可以做手机app的界面。

    26、Vue-CLi是啥?

    它是一个vue.js的脚手架工具。说白了就是一个自动帮你生成好项目目录,配置好Webpack,以及各种依赖包的工具

    27、vue是怎么渲染的?

    1.原有模板语法,挂载渲染:就是对使用Vue标签语法的hmtl进行渲染。
    2.使用render属性,createElement函数直接渲染:原本无html,通过JavaScript 的完全编程的能力生成页面。
    3.使用render属性,配合组件的template属性,createElement函数渲染
    4.使用render属性,配合单文件组件,createElement函数渲染

    28、vue常用的5个事件修饰符
    .stop: 阻止事件冒泡;
    .prevent: 阻止默认事件;
    .capture: 实现捕获触发事件的机制 ;
    .self: 实现只有点击当前元素时候,才会触发事件处理函数 ;
    .once: 事件只触发一次;

    26、vue-router 有哪几种导航钩子?

    第一种:全局导航钩子
    第二种:单独路由独享钩子
    第三种:组件内的钩子

    29、vue-router 路由模式有几种?

    Hash: 使用URL的hash值来作为路由。支持所有浏览器。
    History: 以来HTML5 History API 和服务器配置。参考官网中HTML5 History模式
    Abstract: 支持所有javascript运行模式。如果发现没有浏览器的API,路由会自动强制进入这个模式。

    30、Vue组件通信的六种方法

    • 1.父组件向子组件传值: props/$emit
    • 2.子组件向父组件传值(通过事件形式) $ emit/$on
    • 3.vuex
    • 4.$ attrs/$ listeners
      $ attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$ attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。
      $ listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件
    • 5.provide/inject
    • 6.$parent / $childrenref
      ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
      $parent / $children:访问父 / 子实例

    31、veu中的三要素

    响应式:vue如何监听到 data 每个属性变化?
    vue的响应式原理:Vue在组件和实例初始化的时候,会将data里的数据进行数据劫持(object.definepropty对数据做处理)。被解除过后的数据会有两个属性:一个叫getter,一个叫setter
    getter是使用数据的时候触发,setter是在修改数据的时候触发,修改数据的时候触发setter,同时也触发了底层的watcher(可以收到属性的变化通知并执行相应的函数,从而更新视图。)监听,通知dom修改刷新。

    模板引擎:vue的模板如何被解析,指令如何处理?
    . 本质就是个字符串。模板最终必须转换成JS代码。因为:
    . 有逻辑,如(v-if v-for),必须用JS才能实现
    . 转换为html渲染页面,必须用JS才能实现
    . 因此,模板最重要转化成JS函数(render函数)

    渲染:vue 的模板如何被渲染成 html?
    模板解析成render函数---->返回JS模拟的虚拟DOM结构:模板是一段字符串,模板解析生成render函数,执行render函数返回为vnode,vnode表明了各个节点的层级关系、特性、样式、绑定的事件。
    2、 vnode---->html:通过 updateComponent函数调用vm._update()传入vnode,利用基于snabbdom的patch()方法改造的生成真实DOM节点并渲染页面。

    32、v-if跟v-show的区别

    v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
    v-if判断是否加载,可以减轻服务器的压力,在需要时加载,但有更高的切换开销;
    v-show调整DOM元素的CSS的dispaly属性,可以使客户端操作更加流畅,但有更高的初始渲染开销。
    如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

    33、在ES6中,Promise对象只有三种状态

    异步操作“未完成”(pending)
    异步操作“已完成”(resolved,又称fulfilled)
    异步操作“失败”(rejected)

    34、箭头函数和普通函数的区别

    ,不需要通过function关键字创建函数,并且可以省略return关键字.但函数体内的this对象指的是定义时所在的对象,而不是使用时所在的对象;
    ①不绑定this,箭头函数的this永远指向其父作用域,任何方法都改变不了,包括call,apply,bind。
    普通函数的this指向调用它的那个对象。
    ②箭头函数不能作为构造函数,不能使用new
    ③箭头函数不绑定arguments
    ④箭头函数通过callapply调用,不会改变this指向,只会传入参数
    ⑤箭头函数没有原型属性

    35、ES6有哪些新特性

    1.模板字符串:模板字符串是为了解决使用+号拼接字符串的不便利而出现的
    在这里插入图片描述
    2.解析结构
    在这里插入图片描述

    1. 函数默认参数

    在这里插入图片描述
    4.展开运算符
    在这里插入图片描述
    5.class类

    展开全文
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    举例而言,如要挂载下列5个设备,其执行指令可能如下 (假设都是Linux的ext2系统,如果是Windows XX请将ext2改成vfat): 软盘 ===>mount -t ext2 /dev/fd0 /mnt/floppy cdrom ===>mount -t iso9660 /dev/hdc /mnt/...
  • 2021年前端面试题及答案

    万次阅读 多人点赞 2020-02-11 19:29:34
    3xx:重定向--要完成请求必须进行更进一步的操作 300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内出。如果服务器要提出优先选择,则应该在Location应答头指明。 301 Moved ...

    前端面试汇总(2020年)

    大纲

    1、前言

    2、前端工程化

    3、前端设计模式

    4、前端安全性问题

    5、前端跨域问题

    6、前端数据加密

    7、前端http相关问题

    8、*前端基础知识点面试题

    9、前端技术栈问题

    前言

    由于新冠肺炎疫情,现在成天呆在家里,加上也要准备面试,就在家里看面试题,看着网上一堆面试题,决定收集常见题目汇总一下。关于面试大纲,我认为每个人都是千差万别的。因为面试官都是对简历所写的项目经验进行深挖或者对你所掌握的基本技能进行考察。

    前端工程化

    1

    什么是"前端工程化"?

    前端工程化是使用软件工程的技术和方法来进行前端的开发流程、技术、工具、经验等规范化、标准化,其主要目的为了提高效率和降低成本,即提高开发过程中的开发效率,减少不必要的重复工作时间,而前端工程本质上是软件工程的一种,因此我们应该从软件工程的角度来研究前端工程。

    2

    如何做"前端工程化"?

    前端工程化就是为了让前端开发能够“自成体系”,个人认为主要应该从模块化组件化规范化自动化四个方面思考。

    前端设计模式

    前端常见的设计模式主要有以下几种,具体设计模式查看这篇文章
    1. 单例模式
    2. 工厂模式
    3. 策略模式
    4. 代理模式
    5. 观察者模式
    6. 模块模式
    7. 构造函数模式
    8. 混合模式

    前端安全性问题

    这个是老的话题,有的在初中级前端面试中可能不会提到。但是在高级面试的时候,你要说出前端安全性问题防御,及前端常见安全性问题的攻击原理是什么。

    1

    xss跨站脚本攻击原理?如何进行?防御手段?

    如何进行:如何XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

    主要原理:过于信任客户端提交的数据!

    防御手段:不信任任何客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理然后方可进行下一步的操作。

    2

    CSRF跨站请求伪造原理?如何进行?防御手段?

    如何进行:当你在某网页登录之后,在没有关闭网页的情况下,收到别人的链接。例如:http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=1&password_conf=1&Change=Change#

    点击链接,会利用浏览器的cookie把密码改掉。

    主要原理:在没有关闭相关网页的情况下,点击其他人发来的CSRF链接,利用客户端的cookie直接向服务器发送请求。

    防御手段:

    检测Referer

    Anti-CSRF token机制

    业务上要求用户输入原始密码(简单粗暴),攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF攻击。

    3

    Sql脚本注入原理?如何进行?防御手段?  

    如何进行:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。

    主要原理:通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令

    防御手段:

    使用预编译,绑定变量(推荐)。

    检查数据类型。

    过滤特殊字符和语句。

    页面不错误回显。

    4

    web上传漏洞原理?如何进行?防御手段?  

    如何进行:用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。

    主要原理:当文件上传时没有对文件的格式和上传用户做验证,导致任意用户可以上传任意文件,那么这就是一个上传漏洞。

    防御手段:

    1. 最有效的,将文件上传目录直接设置为不可执行,对于Linux而言,撤销其目录的'x'权限;实际中很多大型网站的上传应用都会放置在独立的存储上作为静态文件处理,一是方便使用缓存加速降低能耗,二是杜绝了脚本执行的可能性;
    2. 文件类型检查:强烈推荐白名单方式,结合MIME Type、后缀检查等方式;此外对于图片的处理可以使用压缩函数或resize函数,处理图片的同时破坏其包含的HTML代码;
    3. 使用随机数改写文件名和文件路径,使得用户不能轻易访问自己上传的文件;
    4. 单独设置文件服务器的域名;

    前端跨越问题

    1

    什么是跨域?  

    由浏览器同源策略限制的一类请求场景,当不同地址,不同端口,不同级别,不同协议就会构成跨域。

    2

    什么是同源策略?  

    所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

    它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。

    3

    如何解决跨域? 能说1,2,7,8就行。

    1、 通过jsonp跨域

    2、CORS

    3、 document.domain + iframe跨域

    4、 location.hash + iframe

    5、 window.name + iframe跨域

    6、 postMessage跨域

    7、 nginx代理跨域

    8、 nodejs中间件代理跨域

    9、 WebSocket协议跨域

    前端数据加密问题

    1

    一般如何处理用户敏感信息?  

    前端一般使用md5、base64加密、sha1加密,想要了解详情请自行百度。

    前端http相关问题

    1

    HTTP常用状态码及其含义?  

    1xx:指示信息--表示请求已接收,继续处理

    100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分。(HTTP 1.1新)

    101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议(HTTP 1.1新)

    2xx:成功--表示请求已被成功接收、理解、接受

    200 OK 一切正常,对GET和POST请求的应答文档跟在后面。

    201 Created 服务器已经创建了文档,Location头给出了它的URL。

    202 Accepted 已经接受请求,但处理尚未完成。

    203 Non-Authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝(HTTP 1.1新)。

    204 No Content 没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。

    205 Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容(HTTP 1.1新)。

    206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新)。

    3xx:重定向--要完成请求必须进行更进一步的操作

    300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。

    301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。

    302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved Temporatily”。出现该状态代码时,浏览器能够自动访问新的URL,因此它是一个很有用的状态代码。注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求http://host/~user(缺少了后面的斜杠),有的服务器返回301,有的则返回302。严格地说,我们只能假定只有当原来的请求是GET时浏览器才会自动重定向。请参见307。

    303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新)。

    304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。

    305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取(HTTP 1.1新)。

    307 Temporary Redirect 和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时 才能重定向。由于这个原因,HTTP 1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。(HTTP 1.1新)

    4xx:客户端错误--请求有语法错误或请求无法实现

    400 Bad Request 请求出现语法错误。

    401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。

    403 Forbidden 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。

    404 Not Found 无法找到指定位置的资源。这也是一个常用的应答。

    405 Method Not Allowed 请求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)对指定的资源不适用。(HTTP 1.1新)

    406 Not Acceptable 指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容(HTTP 1.1新)。

    407 Proxy Authentication Required 类似于401,表示客户必须先经过代理服务器的授权。(HTTP 1.1新)

    408 Request Timeout 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。(HTTP 1.1新)

    409 Conflict 通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。(HTTP 1.1新)

    410 Gone 所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。(HTTP 1.1新)

    411 Length Required 服务器不能处理请求,除非客户发送一个Content-Length头。(HTTP 1.1新)

    412 Precondition Failed 请求头中指定的一些前提条件失败(HTTP 1.1新)。

    413 Request Entity Too Large 目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头(HTTP 1.1新)。

    414 Request URI Too Long URI太长(HTTP 1.1新)。

    416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头。(HTTP 1.1新)

    5xx:服务器端错误--服务器未能实现合法的请求

    500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求。

    501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。

    502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。

    503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头。

    504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。(HTTP 1.1新)505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本。(HTTP 1.1新)

    2

    websocket和轮询及长轮询区别  

    轮询如下:

    客户端:啦啦啦,有没有新信息(Request)服务端:没有(Response)客户端:啦啦啦,有没有新信息(Request)服务端:没有。。(Response)客户端:啦啦啦,有没有新信息(Request)服务端:你好烦啊,没有啊。。(Response)客户端:啦啦啦,有没有新消息(Request)服务端:好啦好啦,有啦给你。(Response)客户端:啦啦啦,有没有新消息(Request)服务端:。。。。。没。。。。没。。。没有(Response) ---- loop

    长轮询如下:

    客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request)服务端:额。。 等待到有消息的时候。。来 给你(Response)客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop

    websocket如下:

    websocket解决了HTTP的这几个难题。 首先,被动性,当服务器完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦。

    所以上面的情景可以做如下修改。

    客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched)客户端:麻烦你有信息的时候推送给我噢。。服务端:ok,有的时候会告诉你的。服务端:balabalabalabala服务端:balabalabalabala服务端:哈哈哈哈哈啊哈哈哈哈服务端:笑死我了哈哈哈哈哈哈哈

    3

    Http和Https的区别?  

    1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

    2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

    3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

    4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    *前端基础知识点面试题

    1

    HTML/5、CSS/3相关  

    一、html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

      新特性:

      HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
      拖拽释放(Drag and drop) API
      语义化更好的内容标签(header,nav,footer,aside,article,section)
      音频、视频API(audio,video)
      画布(Canvas) API
      地理(Geolocation) API
      本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
      sessionStorage 的数据在浏览器关闭后自动删除
      表单控件,calendar、date、time、email、url、search
      新的技术webworker, websocket, Geolocation

      移除元素:
      纯表现的元素:basefont,big,center,font, s,strike,tt,u;
      对可用性产生负面影响的元素:frame,frameset,noframes;
      h5新标签兼容:
      IE8/IE7/IE6支持通过document.createElement方法产生的标签,
      可以利用这一特性让这些浏览器支持HTML5新标签,
      当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架
     
      如何区分:
      DOCTYPE声明\新增的结构元素\功能元素

    二、CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?

      CSS 选择符:

      1.id选择器( # myid)

       2.类选择器(.myclassname)

      3.标签选择器(div, h1, p)

      4.相邻选择器(h1 + p)

      5.子选择器(ul > li)

      6.后代选择器(li a)

      7.通配符选择器( * )

      8.属性选择器(a[rel = "external"])

      9.伪类选择器(a: hover, li:nth-child)

      可以继承的属性:

      可继承的样式: font-size font-family color, UL LI DL DD DT;

      不可继承的样式:border padding margin width height ;

      优先级:

      !important > id > class > tag

      important 比 内联优先级高,但内联比 id 要高

      CSS3新增伪类举例:

      p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。

      p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。

      p:only-of-type 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。

      p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。

      p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。

      :enabled :disabled 控制表单控件的禁用状态。

      :checked 单选框或复选框被选中。

    三、CSS3有哪些新特性?

    更详细的请见:https://www.cnblogs.com/qianduantuanzhang/p/7793638.html

      CSS3实现圆角(border-radius),阴影(box-shadow),

      对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)

      transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜

      增加了更多的CSS选择器 多背景 rgba

      在CSS3中唯一引入的伪元素是::selection.

      媒体查询,多栏布局

      border-image

    四、解释盒模型宽高值得计算方式,边界塌陷,负值作用,box-sizing概念? 

      1. 盒模型:IE 678 下(不添加doctype) 使用ie盒模型,宽度 = 边框 + padding + 内容宽度; chrom、IE9+、(添加doctype) 使用标准盒模型, 宽度 = 内容宽度。 
      2. box-sizing : 为了解决标准黑子和IE盒子的不同,CSS3增添了盒模型属性box-sizing,content-box(默认),border-box 让元素维持IE传统盒子模型, inherit 继承 父盒子模型; 
      3. 边界塌陷:块元素的 top 与 bottom 外边距有时会合并(塌陷)为单个外边距(合并后最大的外边距),这样的现象称之为 外边距塌陷。 
      4. 负值作用:负margin会改变浮动元素的显示位置,即使我的元素写在DOM的后面,我也能让它显示在最前面。

    五、BFC(Block Formatting Context) 是什么?应用? 

      1. BFC 就是 ‘块级格式上下文’ 的格式,创建了BFC的元素就是一个独立的盒子,不过只有BLock-level box可以参与创建BFC,它规定了内部的Bloc-level Box 如何布局,并且与这个独立盒子里的布局不受外部影响,当然它也不会影响到外面的元素。 
      2. 应用场景: 
      1. 解决margin叠加的问题 
      2. 用于布局(overflow: hidden),BFC不会与浮动盒子叠加。 
      3. 用于清除浮动,计算BFC高度。

    六、如何实现浏览器内多个标签页之间的通信?

      调用localstorge、cookies等本地存储方式

    七、简要说一下CSS的元素分类

      块级元素:div,p,h1,form,ul,li;
      行内元素 : span,a,label,input,img,strong,em;

    八、解释下浮动和它的工作原理?清除浮动的方法

      浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。

      1.使用空标签清除浮动。

      这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。

      2.使用after伪对象清除浮动

     该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;

        #parent:after{

      content:".";

      height:0;

      visibility:hidden;

      display:block;

      clear:both;

     }

      3.设置overflow为hidden或者auto

      4.浮动外部元素

    九、CSS隐藏元素的几种方法(至少说出三种)

      Opacity:元素本身依然占据它自己的位置并对网页的布局起作用。它也将响应用户交互;
      Visibility:与 opacity 唯一不同的是它不会响应任何用户交互。此外,元素在读屏软件中也会被隐藏;
      Display:display 设为 none 任何对该元素直接打用户交互操作都不可能生效。此外,读屏软件也不会读到元素的内容。这种方式产生的效果就像元素完全不存在;
      Position:不会影响布局,能让元素保持可以操作;
      Clip-path:clip-path 属性还没有在 IE 或者 Edge 下被完全支持。如果要在你的 clip-path 中使用外部的 SVG 文件,浏览器支持度还要低;

    十、如何让一个盒子水平垂直居中

    复制代码

    复制代码

    //已知宽高<div class="div1"></div><style>
        .div1{
            width:400px;
            height:400px;
            position:absolute;
            left:50%;
            top:50% 
            margin:-200px 0 0 -200px;    }   
    </style>//未知宽高<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title>    <style>
            .div1{
                position: absolute;
                left: 0;
                top: 0;
                bottom: 0;
                right: 0;
                margin: auto;
                border: 1px solid #000;
                width: 400px;
                height: 400px;        }    </style></head><body>    <div class="div1"></div></body></html>//未知宽高方法二:<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title>    <style>
            .div1{
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate(-50%,-50%);
                border: 1px solid #000;
                width: 400px;
                height: 400px;        }    </style></head><body>    <div class="div1"></div></body></html>

    2

    JS部分

    1、cookie、localStorage、sessionStorage的区别和使用?

    cookie:是存储在本地的数据,有时候也用cookies,通常经过加密,应用最经典的就是判断注册用户是否已经登录过该网站。   localStorage:仅在客户端保存(即浏览器),不参与和服务器的通信;没有时间限制,即使浏览器关闭,数据依然存在;
       创建和访问localStorage:
            1)、设置数据:
            var forgetData = {phone:vm.phone};        localStorage.setItem("forgetData",JSON.Stringfy(forgetData));    //forgetData是存储在localStorage里边的本地数据;JSON.Stringfy(forgetData)是将数据转化为字符串格式;
                获取数据:
            vm.forgetData=JSON.parse(localStorage.getItem("forgetData"));  //将字符串转化为JSON化;
            2)、设置:localStorage.name = "zhao";
                 获取:localStorage.name    //zhao        localStorage.setItem(key,value);//设置数据        localStorage.getItem(key);//获取数据        localStorage.removeItem(key);//删除单个数据        localStorage.clear();//清除所有localStorage的数据
    
        sessionStorage:当用户的浏览器窗口关闭时,数据会被清除;
        
        共同点:都是保存在浏览器端,且同源的。
        区别:
            cookie数据始终在同源的http请求中携带9即使不需要),即cookie在浏览器和服务器之间来回传递;cookie数据还有路径的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据大小不能超过4K,同时因为每次http请求都会携带cookie,所以cookie只能保存很小的数据。
            sessionStorage和localStorage不会自动把数据发给服务器,只在本地保存,虽然也有大小限制,但是要比cookie大得多,可以达到5M或者更大。
            数据有效期不同,sessionStorage仅在当前浏览器窗口关闭前有效,不能持久保存;localStorage:始终有效,浏览器窗口关闭也一直保存;cookie:只在cookie设置的过期时间之前保存,即使浏览器窗口关闭。
            作用域不同,sessionStorage在不同浏览器窗口的数据不能共享,即使是同一个页面;localStorage在所有的同源窗口中都是共享的;cookie也是在同源窗口中共享的,

    2、如何实现浏览器多标签页之间的通信?

        调用localStorage、cookie本地存储方式。

    3、JavaScript的typeof返回类型有哪些?

    Object(null和Array)、number、undefined、string、Boolean、function

    4、类型转换

    强制转换:parseInt();parseFloat();number();

    5、数组的方法

    var list = [1,2,3];list.pop();//删除数组的最后一个元素 var list = [1,2];list.unshift(0,1);//头部添加  var list = [0,1,1,2,3];list.push(4,5);//尾部添加   var list = [1,2,3,4,5];var arr = list.concat(4,[5,6]);//把两个数组连接起来 //var arr = [1,2,3,4,5];  //var list = [1,2,3];list.join("-");    //1-2-3list.reverse();//3,2,1list.slice(1);//var list = [2,3];list.slice(1,2);//var list = [2];list.slice(1,-2);//设置了两个参数,终止下标为负数,当出现负数时,将负数加上数组长度的值来替换该位置的数。var arr = list.splice(0,1);//删除 var list = [2,3];  var arr = [1];可以删除任意数量的项,只需指定2个参数;要删除的第一项的位置和要删除的项数。例如splice(0,2);会删除当前数组的前两项list.splice(2,0,4,6);//插入,var list = [1,2,4,6,3]; 可以向指定位置插入任意数量的项,需要3个参数,起始位置、0(要删除的项数)、要插入的任意数量的项。例如splice(2,0,4,6);会从第二个位置插入4和6;list.splice(2,1,4,6);//替换,var list = [1,2,6,3]; 可以向指定位置插入任意数量的项,同时删除任意数量的项,需要3个参数,起始位置、要删除的项数、要插入的任意数量的项。例如splice(2,1,4,6);会从位置 2 开始插入4和6。list.sort();//按照第一个数字大小进行排序;function compare(a,b){
        return a-b;//正序;
        return b-a;//倒序;}list.sort(compare);

    6、ajax请求时get和post的区别?

    get:从服务器上获取数据,传送数据量小,安全性低,请求会被缓存,缓存是针对URL进行缓存的,get请求参数直接加在URL地址后面,一种参数组合就会产生一种URL的缓存,重复的请求结果是相同的;post:向服务器发送数据;传送数据量大,请求不会被缓存,参数封装在二进制的数据体中,服务器也不会记录参数,相对安全,所以涉及用户隐私的数据都要用post传送;

    7、ajax请求时,如何解释json数据?

    使用eval方法解析的时候,eval();不会去判断该字符串是否合法,而且json对象里的js方法也会被执行,这是非常危险的;推荐使用JSON.parse(); JSON.parse();把字符串转化成json。

    8、call和apply的区别?

    共同点:
        都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。
        另一种说法,都能够改变方法的执行上下文(执行环境),将一个对象的方法交给另一个对象来执行,并且是立即执行。
    不同点:
        apply();//最多只能有两个参数--新this对象和一个数组argArray,如果给该方法传递多个参数,则把参数都写进这个数组里边,当然,即使只有一个参数,也要写进数组里边。
        call();//可以接收多个参数,第一个参数apply()一样,后面则是一串参数列表。
        实际上,apply和call的功能是一样的,只是传入的参数列表的形式不同。

    9、http常用状态码?

        100  Continue  继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息    200  OK   正常返回信息    201  Created  请求成功并且服务器创建了新的资源    202  Accepted  服务器已接受请求,但尚未处理    301  Moved Permanently  请求的网页已永久移动到新位置。    302 Found  临时性重定向。    303 See Other  临时性重定向,且总是使用 GET 请求新的 URI。    304  Not Modified  自从上次请求后,请求的网页未修改过。    400 Bad Request  服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。    401 Unauthorized  请求未授权。    403 Forbidden  禁止访问。    404 Not Found  找不到如何与 URI 相匹配的资源。    500 Internal Server Error  最常见的服务器端错误。    503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。

    10.你有哪些性能优化的方法?

        (详情请看雅虎14条性能优化原则)。
    
          (1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
    
          (2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
    
          (3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
    
          (4) 当需要设置的样式很多时设置className而不是直接操作style。
    
          (5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
    
          (6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
    
          (7) 图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳。

    11.深拷贝和浅拷贝

        基本类型指的是简单的数据段,引用类型指的是多个值构成的对象;    var name = "John"; // 基本类型值
    
        var obj = new Object(); 
        obj.name = "John"; 
        // obj 为引用类型值
        
        在复制变量中,对于基本类型来说,两者互不影响,    var num = 1;    var num1 = num; // num1 = 1;
    
        var num1 = 3; // num还是1,不会变
        
        浅拷贝和深拷贝的区别:
        对于浅拷贝来说,对于一个数组(数组是一个对象),只要我们修改了一个拷贝数组,原数组也会跟着改变。
        因为他们引用的是同一个地址的数据,拷贝的时候并没有给b数组创造独立的内存,只是把a数组指向数据的指针拷贝给了b;
        而深拷贝就与其相反,将会给b数组创造独立的内存,并且将a数组的内容一一拷贝进来,两者互不影响。
        
        实现深拷贝:
        一:层级拷贝,用递归实现;
        二:JSON解析        var b = JSON.parse(JSON.stringify(a));        

    3

    其他  

    一、怎么让Chrome支持小于12px 的文字?

    这个我们在做移动端的时候,设计师图片上的文字假如是10px,我们实现在网页上之后。往往设计师回来找我们,这个字体能小一些吗?我设计的是10px?为啥是12px?其实我们都知道,谷歌Chrome最小字体是12px,不管你设置成8px还是10px,在浏览器中只会显示12px,那么如何解决这个坑爹的问题呢?

    我们的做法是:

    针对谷歌浏览器内核,加webkit前缀,用transform:scale()这个属性进行缩放!

    <style>pspan{font-size:10px;-webkit-transform:scale(0.8);display:block;}</style><p><span>haorooms博客测试10px</span></p>

    二、IOS手机浏览器字体齿轮

    修改-webkit-font-smoothing属性,结果是:-webkit-font-smoothing:none:无抗锯齿-webkit-font-smoothing: antialiased | subpixel-antialiased |default:灰度平滑

    三、如何修改chrome记住密码后自动填充表单的黄色背景?

    大体可以通过input : -webkit-autofill来进行修改!

    input:-webkit-autofill {background-color:#FAFFBD;background-image: none;color:#000;}

    四、谷歌浏览器运行下面代码,并解释!

    [].forEach.call($$("*"),function(a){ a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)})

    运行上面代码之后,会发现HTML层都被使用不同的颜色添加了一个高亮的边框。为什么会这样呢?

    首先我们来看

    [].forEach.call(),关于call()和apply(),我前面有文章也写过,具体可以看http://www.haorooms.com/post/js_constructor_pro

    [].forEach.call()等价于Array.prototype.forEach.call()

    其次我们来看$$("*")

    你可以在你的Chrome浏览器控制台中输入$$('a'),然后你就能得到一个当前页面中所有锚元素的列表。

    $$函数是许多现代浏览器命令行API中的一个部分,它等价于document.querySelectorAll,你可以将一个CSS选择器作为这个函数的参数,然后你就能够获得当前页面中所有匹配这个CSS选择器的元素列表。如果你在浏览器控制台以外的地方,你可以使用document.querySelectorAll('')来代替$$('')

    为元素添加颜色

    为了让元素都有一个漂亮的边框,我们在上面的代码中使用了CSS属性outline。outline属性位于CSS盒模型之外,因此它并不影响元素的属性或者元素在布局中的位置,这对于我们来说非常有用。这个属性和修改border属性非常类似,因此下面的代码应该不会很难理解:

    a.style.outline="1px solid #"+ color

    真正有趣的地方在于定义颜色部分:

    (~~(Math.random()*(1<<24))).toString(16)

    ~~的作用相当于parseInt,和我前面讲解的“|”功能类似,关于运算符“I” ,可以去看看!

    通过上面代码可以获取到一个随机的颜色值!

    五、input [type=search] 搜索框右侧小图标如何美化?

    美化效果如下图:

    enter image description here

    右侧默认的比较难看的按钮,美化成右侧效果。

    input[type="search"]::-webkit-search-cancel-button{-webkit-appearance: none;height:15px;width:15px;border-radius:8px;background:url("images/searchicon.png")no-repeat 00;background-size:15px15px;}

    用到的是伪元素::-webkit-search-cancel-button,关于什么是伪类和为元素,请看:http://www.haorooms.com/post/css_wl_wys

    六、iOS safari 如何阻止“橡皮筋效果”?

    可以参考一下知乎上的回答 https://www.zhihu.com/question/22256539 。

    但是,我们遇到的问题不是这样,我是要解决弹跳导致弹出层(position:absolute)的覆盖层高度小于100%;

    针对这个问题,我想到的解决方案如下:

    方法一: 把position:absolute改成position:fixed,并在弹出层之后,设置body的高度是100%;overflow是hidden。

    方法二:

    思路是获取苹果浏览器导航栏的高度。然后滚动的时候,重新获取其高度。在导航栏高度变小的时候,给弹出层增加高度的百分比!

    代码如下:

    //ios safari 伸缩判断var topbarHeight=window.outerHeight-window.innerHeight,agent=navigator.userAgent,globleflag=true;
            $(window).scroll(function(){if(agent.indexOf("iPhone")!=-1|| agent.indexOf("iPad")!=-1){var topbarHeightNow=window.outerHeight-window.innerHeight;if(topbarHeightNow<topbarHeight){
                        globleflag=false//此处写处理逻辑}else{
                     globleflag=true//此处写处理逻辑}}});

    七、实现点击文字,文字后面radio选中效果

    这个效果是前端很经常用到和遇到的效果了,实现这个效果的方式也很多,很多朋友用js和jquery来实现,但是最简单的,我们可以直接用lable标签的 for 属性来实现。

    看下下面例子:

    <form><labelfor="male">Male</label><inputtype="radio"name="sex"id="male"/><br/><labelfor="female">Female</label><inputtype="radio"name="sex"id="female"/></form>

    label 的for属性后面跟着input的id,就可以点击label,来触发input效果了,大家可以试一试!

    八、网站中,图片文件(jpg,png,gif),如何点击下载?而非点击预览?

    我们平时在网站中的图片,假如我们要下载,如下写:

    <ahref="haorooms博客.jpg">下载</a>

    我们点击下载按钮,只会预览“haorooms博客.jpg”这张图片,并不会出现下载框,另存为那种?那么我们如何做呢?

    我们只需要如下写

    <ahref="haorooms博客.jpg"download>下载</a>

    就可以下载了。点击如下进行尝试吧!下载

    不但如次,我们还可以指定文件名称,如下写法:

    <ahref="haorooms博客.jpg"download="haoroom前端博客图片下载">下载</a>

    测试如下:下载

    上面就是指定下载的写法!

    九、Math.min()比Math.max()大

    Math.min()<Math.max()// falseMath.min()>Math.max()// true

    因为Math.min() 返回 Infinity, 而 Math.max()返回 -Infinity。

    前端技术栈问题

    1

    vue相关问题?  

    更多前端技能请关注公众号”极致简文“

    往期精彩回顾

    React组件与生命周期

    React函数组件和Class组件以及Hooks

    2020年最火爆的Vue.js面试题

    Redux使用之我要买个女朋友(入门篇)

    关注公众号,精彩不间断

    展开全文
  • 前端面试题

    万次阅读 多人点赞 2019-08-08 11:49:01
    出display的值,说明他们的作用。position的值, relative和absolute定位原点是? 40 absolute的containing block计算方式跟正常流有什么不同? 40 对WEB标准以及W3C的理解与认识 41 css的基本语句构成是? ...
  • 测试开发笔记

    万次阅读 多人点赞 2019-11-14 17:11:58
    ★需求的跟踪 78 需求跟踪矩阵的作用: 78 需求的特点: 79 需求工程 79 变更控制流程图 82 第九章 缺陷管理 83 缺陷相关概念 83 缺陷管理相关概念 83 BUG管理基本流程: 84 BUG单 84 第十章 测试需求分析 86 概念:...
  • java面试题2019_java面试题及答案_java面试题库

    千次阅读 多人点赞 2019-05-16 09:31:30
    1、一个.java源文件中是否...4、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 5、short s1 = 1; s1 = s1 + 1;有什么错?short s1 = 1; s1 += 1;有什么错? 6、char型变量中能不能存贮一个中...
  • 【数据库学习】数据库总结

    万次阅读 多人点赞 2018-07-26 13:26:41
    举例: 有这样一个关系 ,假设一个产品只能放到一个仓库中,但是一个仓库可以有若干管理员,那么对应于一个 有一个仓库号,而实际上,这个仓库号只与库存产品号有关,与管理员无关,就说这是多值依赖。 2)范式 ...
  • 纳什均衡定义举例、分类

    千次阅读 多人点赞 2020-07-08 10:02:18
    纳什均衡在不同的领域的定义不尽相同,但是中心思想是相同的,即在非合作博弈中,双方为使自己利益最大化,而最终达到的一个均衡状态。在这个状态下,当所有其他人不改变策略,任意一方也不会(没有理由/动力)改变...
  • 测试开发需要学习的知识结构

    万次阅读 多人点赞 2018-04-12 10:40:58
    贯穿程序的独立路径数是天文数字。但即使每条路径都测试了仍然可能有错误。第一,穷举路径测试决不能查出程序违反了设计规范,即程序本身是个错误的程序。第二,穷举路径测试不可能查出程序中因遗漏路径而出错。第三...
  • Java poi Excel xls数字转字母

    千次阅读 2016-12-02 16:24:42
    因为是按月导出 一个月最多31天,所以刚开始采用的办法是定义一个包含1到31字母的数组。后来想想这样总不是个办法 万一数更多 且是不确定的呢。于是研究了下 怎么把xls数字列号转成对应的字母。
  • 【MATLAB】MATLAB的基础知识

    千次阅读 多人点赞 2017-04-12 11:52:00
    for循环语句则执行过程是:从表达式的第一开始,依次将表达式(矩阵)的各之值赋值给变量,然后执行语句组中的语句,直到最后一。 for 语句的典型格式是表达式为冒号运算的行向量,即: for i=m:p:n ...
  • WPF开发教程

    万次阅读 多人点赞 2019-07-02 23:13:20
    某些包含元素(如 Grid 布局元素)通常需要子元素上的其他数据才能控制其行为(如行/信息)。任何对象都可以为任何其他对象提供属性定义,而不是要将所有这些属性与每个元素相关联。这与 JavaScript 中的“expando...
  • 基于FPGA的数字识别实现

    千次阅读 2019-07-21 17:30:34
    本篇博客就将介绍数字识别的方法,由于只是研究数字识别的方法,我们就不用硬件平台,而是用Modelsim和Matlab来仿真验证。 具体方法如下: 我们用画图软件将带有数字的图片截取为640x480像素,为了和我们将来要使用...
  • 图上所标数字为各节点之间的运输距离,为使总运费最少,必须找出一条由A至E总里程最短的路线。 图1 为了找到由A至E的最短线路,可以将该问题分成A—B—C—D—E 4个阶段,在每个阶段都需要作出决策,即在A点需决策下...
  • C语言之输入输出

    万次阅读 多人点赞 2019-04-30 00:03:47
    矩阵一般在大学的《高等数学》中会讲到,m×n 的数字矩阵可以理解为把 m×n 个数字摆放成 m 行 n 的样子。 看,这是多么地自虐,要敲那么多空格,还要严格控制空格数,否则输出就会错位。更加恶心的是,如果数字...
  • verilog 综合注意事项

    万次阅读 多人点赞 2016-07-29 15:46:40
    6、always过程块描述组合逻辑,应在敏感信号表中出所有的输入信号; 7、所有的内部寄存器都应该可以被复位; 8、用户自定义原件(UDP元件)是不能被综合的。 一:基本 Verilog中的变量有线网类型和寄存器...
  • 《数据库系统概论》复习

    千次阅读 多人点赞 2019-05-27 12:13:27
    基本关系的6条性质:同质、异可同域、行列无序性、候选码唯一性、分量原子性 2、关系模式 关系模式:关系的描述称为模式,它的形式化表达为R(U,D,DOM,F),其中R为关系名,U为属性名集合,D为属性域,DOM为...
  • Linux实用教程(第三版)

    万次阅读 多人点赞 2019-08-27 22:55:59
    分区命名方案 Linux系统使用字母和数字的组合来指代硬盘分区,使用一种更加灵活的分区命名方案,该命名方案是基于文件的,文件名的格式为/dev/xxyN(比如/dev/sda1分区)。 /dev:这是Linux系统中所有设备文件所在...
  • 定义:如果关系R 中所有属性的值域都是单纯域,那么关系模式R是第一范式的 那么符合第一模式的特点就有 1)有主关键字 2)主键不能为空, 3)主键不能重复, 4)字段不可以再分 例如:  StudyNo | Name | Sex...
  • MATLAB函数速查手册

    千次阅读 多人点赞 2018-03-25 09:06:26
     2.1.4 syms函数–定义矩阵的又一函数   2.1.5 sym的另一职能–把数值矩阵转化成相应的符号矩阵   2.1.6 创建大矩阵   2.1.7 cat函数–创建多维数组   2.1.8 zeros函数–零矩阵的生成   2.1.9 eye...
  • C语言数字图像处理---1.1图像的像素格式与图像读写

    千次阅读 多人点赞 2019-12-25 10:06:22
    前言 本专栏面向所有希望或有兴趣从事数字图像处理工作、学习或研究的朋友,不懂MATLAB和OPENCV没关系,仅需要基础的C语言知识,便可以通过本专栏内容轻松入门数字图像处理方向。
  • 计算机组成原理答案

    万次阅读 多人点赞 2018-12-19 21:11:27
    举例说明专用计算机和通用计算机的区别。 答:按照计算机的效率、速度、价格和运行的经济性和实用性可以将计算机划分为通用计算机和专用计算机。通用计算机适应性强,但牺牲了效率、速度和经济性,而专用计算机是...
  • HTML简介及举例

    千次阅读 2014-08-31 14:54:37
     定义列表:自定义列表不仅仅是一项目,而是项目及其注释的组合。自定义列表以标签开始。每个自定义列表项以开始。每个自定义列表项的定义以开始。定义列表的列表项内部可以使用段落、换行符、图片、链接以及其他...
  • 软件测试:等价类划分举例

    万次阅读 2018-04-24 17:03:45
    出等价类表并编号 覆盖有效等价类的测试用例:  a b c  覆盖等价类号码  3 4 5  ( 1 ) -- ( 7 )  4 4 5  ( 1 ) -- ( 7 ),( 8 )  4 5 5  ( 1 ) -- ( 7 ),( 9 )    5 4 5  ...
  • 定义一个3行4的整型二维数组,输入一组数据,找出鞍点。所谓鞍点就是该位置上的元素在该行最大,在该上最小,一个矩阵中最多只有一个鞍点,也有可能没有鞍点。
  • C语言指针用法和举例

    千次阅读 2020-08-20 09:55:29
    二,指针的作用 1、堆内存无法取名字(无法使用标识符与堆内存建立联系),必须配合指针。 2、函数之间的参数是值传递(内存拷贝),使用指针可以优化参数的传递效率(需要对变量进行保护)。因为C语言采用的是值...
  • shell脚本总结

    千次阅读 多人点赞 2014-07-02 21:52:35
    举例 子 grep -n “your” www # 文件 www 中查找含有 your 单词的行,且输出行号 grep -nw “your” www # 文件 www 中查找含以 your 做单词的行,且输出行号 grep -nr ‘[a-zA-Z0-9].you’ ./...
  • 1.1-做了这么久,才知道什么是上位机

    万次阅读 多人点赞 2020-02-09 17:12:16
    一、定义 上位机: 上位机指可以直接发送操作指令的计算机或单片机,一般提供用户操作交互界面并向用户展示反馈数据。 典型设备类型:电脑,手机,平板,面板,触摸屏 下位机: 下位机指直接与机器相连接的计算机或...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 60,899
精华内容 24,359
关键字:

列数字的定义作用举例