练习题

Posted gzying-01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了练习题相关的知识,希望对你有一定的参考价值。

深圳骑士计划脱产班全栈3期统一考试

 

深圳骑士计划脱产班全栈3期第三次统一考试

考试时长:5个小时                   满分:150分

 

评分标准(150分):  (150, ‘A+‘), (136, ‘A‘), (129, ‘B+‘), (121, ‘B‘), (106, ‘B-‘), (91, ‘C+‘), (76, ‘C‘), (61, ‘C-‘), (0, ‘ D‘)

 

1.请编写一个函数实现将IP地址转换成一个整数。(5分)

 

如 10.3.9.12 转换规则为:

        10            00001010


         3            00000011

         9            00001001


        12            00001100

再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?

答:

技术图片
# -*- coding: utf-8 -*-
# __author: Tiger_Lee
# @file: 考试题.py
# @time: 2019 02 26
# @email: [email protected]


# 赠送内容:用Python获取本机ip地址

from socket import gethostbyname_ex, gethostname


local_IP_list = gethostbyname_ex(gethostname())
local_IP = gethostbyname_ex(gethostname())[2][0]


def decimal_to_binary(ip_add):
    """
    将ip地址转换为二进制
    :param ip_add: 
    :return: 
    """
    num_list = ip_add.split(".")
    ip_binary = ""
    for num in num_list:
        num = bin(int(num))[2:]
        binary_num = num.rjust(8, ‘0‘)
        ip_binary += binary_num + " "

    return ip_binary[:-1]


binary_ip = decimal_to_binary(local_IP)
print(binary_ip)


def binary_to_decimal(binary):
    """
    将二进制转换为IP地址
    :param binary: 
    :return: 
    """
    ip_str = ""
    binary_list = binary.split(" ")
    for num in binary_list:
        ip_str += str(int(num, 2)) + "."

    return ip_str[:-1]


print(binary_to_decimal(binary_ip))
技术图片

 

2.python递归的默认最大层数(1分),怎么更改其默认最大层数?(2分)(本题总分3分)

技术图片
# import sys
# sys.setrecursionlimit(100000)
#
# def func(n):
#     print(n)
#     n += 1
#     func(n)
#
# func(0)
技术图片

 

3.请写出print的结果:(3分)

    v1 = 1 or 3

    v2 = 1 and 3

    v3 = 0 and 2 and 1

    v4 = 0 and 2 or 1

    v5 = 0 and 2 or 1 or 4

    v6 = 0 or False and 1

    print(v1, v2, v3, v4, v5, v6)

答:

1,3,0,1,1,False

 

4.用一行代码实现数值交换:(2分)


     a = 1

     b = 2

答:

a, b = b, a

 

5.如何安装第三方模块?(1分)以及用过哪些第三方模块?(2分)(本题总分3分)

方法1:pip install 第三方模块
方法2:pycharm中鼠标操作

用过:greenlet gevent pymysql socket

 

6.谈谈你对闭包的理解?(2分)并写一个闭包函数。(2分)(本题总分4分)

技术图片
内层函数对外层函数非全局变量的引用,该内部函数称为闭包函数

def func():
    name = ‘666‘
    def inner():
        print(name)
    return inner


f = func()
f()
技术图片

 

7.什么是反射?(2分)以及应用场景?(2分)(本题总分4分)

技术图片
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
应用场景:

class Foo:
    f = ‘类的静态变量‘
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def say_hi(self):
        print(‘hi,%s‘%self.name)


obj=Foo(‘egon‘,73)


#检测是否含有某属性
print(hasattr(obj,‘name‘))
print(hasattr(obj,‘say_hi‘))

#获取属性
n=getattr(obj,‘name‘)
print(n)
func=getattr(obj,‘say_hi‘)
func()
print(getattr(obj,‘aaaaaaaa‘,‘不存在啊‘)) #报错


#设置属性
setattr(obj,‘sb‘,True)
setattr(obj,‘show_name‘,lambda self:self.name+‘sb‘)
print(obj.__dict__)
print(obj.show_name(obj))


#删除属性
delattr(obj,‘age‘)
delattr(obj,‘show_name‘)
delattr(obj,‘show_name111‘)#不存在,则报错
print(obj.__dict__)
技术图片

 

8.什么是面向对象的mro?(3分)

答 :

对于你定义的每一个类,Python 会计算出一个方法解析顺序(Method Resolution Order, MRO)列表,它代表了新式类中类继承的顺序

 

9.简述 yield和yield from关键字。(3分)

答 :

在python中用yield和yield from都是构造一个生成器函数

yield后面返回的是一个值
yield from则是直接返回一个生成器

 

10.简述 OSI 七层协议。(写出7层2分,简述每一层总分3分)(本题总分5分)

答 :

技术图片
应用层  网络服务与最终用户的一个接口。
             常见协议:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP

表示层  数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)
             格式有,JPEG、ASCll、DECOIC、加密格式等

会话层  建立、管理、终止会话。(在五层模型里面已经合并到了应用层)
             对应主机进程,指本地主机与远程主机正在进行的会话

传输层  定义传输数据的协议端口号,以及流控和差错校验。
             常见协议:TCP UDP,数据包一旦离开网卡即进入网络传输层
             常见的物理设备 :四层路由器、四层交换机

网络层  进行逻辑地址寻址,实现不同网络之间的路径选择。
             常见协议:ICMP IGMP IP(IPV4 IPV6) ARP RARP
             常见物理设备:路由器、三层交换机

数据链路层 建立逻辑连接、进行硬件地址寻址、差错校验 [2]  等功能。(由底层网络定义协议)
             将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。
            ,常见协议:ARP协议
             常见物理设备:网桥、以太网交换机、网卡

物理层  建立、维护、断开物理连接。(由底层网络定义协议)
             常见物理设备:中继器、集线器、双绞线
技术图片

 

11.什么是C/S和B/S架构?(2分)

答 :

技术图片
Client与Server ,中文意思:客户端与服务器端架构,这种架构也是从用户层面(也可以是物理层面)来划分的。
这里的客户端一般泛指客户端应用程序EXE,程序需要先安装后,才能运行在用户的电脑上,对用户的电脑操作系统环境依赖较大。

B/S即:Browser与Server,中文意思:浏览器端与服务器端架构,这种架构是从用户层面来划分的。
Browser浏览器,其实也是一种Client客户端,只是这个客户端不需要大家去安装什么应用程序,只需在浏览器上通过HTTP请求服务器端相关的资源(网页资源),客户端Browser浏览器就能进行增删改查。
技术图片

 

12.简述 三次握手、四次挥手的流程。(4分)

技术图片
TCP的三次握手

TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK[1],并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接。[1]

TCP三次握手的过程如下:
客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。


TCP的四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭(half-close)造成的。
(1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
(2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
(3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
(4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。[1]
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。

注意:
(1) “通常”是指,某些情况下,步骤1的FIN随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。[2]
(2) 在步骤2与步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这称为“半关闭”(half-close)。
(3) 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。
无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。[2]
技术图片

 

13.什么是arp协议?(2分)

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。

 

14.TCP和UDP的区别?(3分)

TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

 

15.为何基于tcp协议的通信比基于udp协议的通信更可靠?(2分)

当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,流量控制等功能,保证能从一端传到另一端。

 

16.什么是粘包?(1分) socket 中造成粘包的原因是什么?(2分) 哪些情况会发生粘包现象?(2分)(本题总分5分)

粘包 :在tcp协议中,几条连续发送的数据在接收端粘在一起。
粘包成因 :本质是发送信息与接受信息的边界不清晰造成的
哪些情况会发生粘包 :发送端的缓存机制、接收端的缓存机制

 

17.什么是进程?(2分)请简述进程的三个状态?(2分)(本题总分4分)

在运行中的程序就是进程
进程是计算机中最小的资源分配单位
进程的三状态 :就绪 运行 阻塞

 

18.什么是线程?(3分)

线程是计算机中能被CPU调度的最小单位

 

19.简述 进程、线程、协程的区别?(3分) 以及应用场景?(3分)(本题总分6分)

进程:数据隔离,可以利用多核,会产生数据不安全的现象。常用于数据隔离度高的高计算型场景

线程:数据共享,在python中不能利用多核,操作系统级别,会产生数据不安全的现象。常用于数据隔离度低的高IO型场景。

协程:数据共享,不能利用多核,用户级,操作系统不可见,不存在数据安全问题。常用于数据隔离度低的高IO型场景。

 

20.GIL是什么?(3分)

全局解释器锁。

该锁是Cpython解释器中特有的

保证了同一个python进程中的多个线程同一时刻只能有一条线程访问CPU。

 

21.Python中如何使用线程池和进程池?(4分)

技术图片
线程池
from concurrent.futures import ThreadPoolExecutor
p = ThreadPoolExecutor(5)

进程池
from concurrent.futures import ProcessPoolExecutor
p = ProcessPoolExecutor(5)
技术图片

 

22.进程之间如何进行通信?(3分)

可以通过原生socket通信

如果是在同一个进程中,也可以使用multiprocessing自带的pipe或者queue进行通信

也可以使用第三方工具:memcache、redis、kafka、rabbitmq

 

23.什么是并发和并行?(3分)

并行 : 并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑;(资源够用,比如三个线程,四核的CPU )

并发 : 并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率。

 

24.你知道几种锁(请列出)?(1分)并解释它们的作用和区别?(3分)(本题总分4分)

互斥锁和递归锁 都是为了保证在并发编程中的数据安全问题

互斥锁 :在一个进程或者线程单位中只能连续调用一次,否则就会发生死锁现象

递归锁 :在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock

 

25.解释什么是异步非阻塞?(4分)

异步:程序在做多件事情的时候,不必按照顺序执行,可以各自执行各自的不受干扰

非阻塞:程序中没有阻塞现象

 

26.简述 gevent模块的作用和应用场景?(4分)

协程模块

可以用来规避单线程中的IO操作,提高线程对CPU的利用率
可用于 爬虫等IO操作比较频繁的网络应用场景

 

27.请实现功能 : 在不改变装饰器的情况下,给装饰器的执行加上log信息。(5分)

def log(wrap):

   …

@log              

def wrapper(func):

    def inner(*args,**kwargs):

        print(‘before func‘)

        ret =  func(*args,**kwargs)

        print(‘after func‘)

        return ret

    return inner

 

@wrapper        

def wahaha(name):

    print(‘%s in wahaha‘%name)

 

wahaha(‘alex‘)

 

答:

技术图片
def log(wrap):
    def log_inner(*args,**kwargs):
        inn = wrap(*args,**kwargs)
        def inner(*args,**kwargs):
            ret = inn(*args,**kwargs)
            print(wrap.__name__,‘is running‘)
            return ret

        return inner

    return log_inner


@log              
def wrapper(func):
    def inner(*args,**kwargs):
        print(‘before func‘)
        ret =  func(*args,**kwargs)
        print(‘after func‘)

        return ret

    return inner

 

@wrapper         
def wahaha(name):
    print(‘%s in wahaha‘%name)


wahaha(‘alex‘)
技术图片

 

28.写代码得到两个列表的交集和差集?(4分)

l1 = [1,2,3]

l2 = [2,3,4]

技术图片
# 交集
print(set(l1) & set(l2))
print(set(l1).intersection(set(l2)))

# 差集
print(set(l1) - set(l2))
print(set(l1).difference(set(l2)))
技术图片

 

29.用python正则匹配字符串,<.*>和<.*?>有什么区别?(3分)

技术图片
<.*>是正则默认的贪婪匹配模式,会直接匹配到最后一个>
<.*?>是正则表达式的惰性匹配模式,会匹配到第一个>
例如 <h1>hahaha<h1>

<.*> 匹配的结果是一个  <h1>hahaha<h1>
<.*?> 匹配的结果是两个<h1>和<h1>
技术图片

 

30.读代码写出代码运行后的结果,并解释执行过程?(6分)

def func(num):

    n, a, b = 0, 0, 1

    while n < num:

        yield b

        print(b, ‘in func‘)

        a, b = b, a + b

        n = n + 1

for i in func(5):

    print(i)

技术图片
yield: 带有yield的函数是一个迭代器,函数返回某个值时,会停留在某个位置,返回函数值后,会在前面停留的位置继续执行,直到程序结束

结果是: 1 1 in func 1 1 in func 2 2 in func 3 3 in func 5 5 in func
技术图片

 

31.用Python实现一个二分查找的函数。(6分)

二分查找算法

32.读代码写答案:(4分)

(1)

a = range(10)

b = range(20)

z = zip(a, b)

print(len(list(z)))  # 请写出打印结果

print(len(list(z)))  # 请写出打印结果

答:

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

执行结果:
10 0

(2)

def func(n):

    return n % 2 == 1

newlist = filter(func, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

print(list(newlist))  # 请写出打印结果

答:

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
执行结果:
[1, 3, 5, 7, 9]

(3)

a = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

print(list(a))  # 请写出打印结果

答:

map() 会根据提供的函数对指定序列做映射。

执行结果:
[3, 7, 11, 15, 19]

 

33.读代码写出打印的结果,并解释为什么是这样。(6分)

class A(object):

    def func(self):

        print(‘A‘)

 

class B(A):

    def func(self):

        super().func()

        print(‘B‘)

 

class C(A):

    def func(self):

        super().func()

        print(‘C‘)

 

class D(B,C):

    def func(self):

        super().func()

        print(‘D‘)

 

D().func()

答案:

技术图片
A
C
B
D

这是新式类的继承顺序导致的,根据c3算法或者mro方法给出的结论都可以得出。
技术图片

 

34.列举你所知道的面向对象的特殊方法,及其应用?(5分,每写一个得0.5分)

技术图片
__len__   len 一个对象就会触发 __len__方法。
__hash__()方法应该返回一个32位长的整数,对与同一个对象,__hash__()方法应该总是返回相同的值
__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
__repr__ 如果一个类中定义了__repr__方法,那么在repr(对象) 时,默认输出该方法的返回值。
__call__ 方法的执行是由对象后加括号触发的
__eq__ x==y 运算将会调用实例x的__eq__(self, other)方法
__del__  析构方法,当对象在内存中被释放时,自动触发执行。
__new__ 构造方法__new__的执行是由创建对象触发的,即:对象 = 类名() 

item系列将对象视为字典使用时,就会触发item方法
__getitem__
__setitem__
__delitem__
__delattr__
技术图片

 

35.用尽量多的方法实现单例模式。(8分)

技术图片
class A:
    __instance = None

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

    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = object.__new__(cls)
            cls.__instance = obj
        return cls.__instance
技术图片

 

36.读代码回答其中的问题:(本题总分12分)

(1)

import threading

import time

 

def _wait():

    time.sleep(60)

# FlagA

t = threading.Thread(target=_wait, daemon=False)

t.start()

# FlagB

 

# 问:程序从FlagA执行到FlagB的时间大致为多少秒?并简述为什么?(2分)

0秒左右,因为创建一个线程并启动它的时间非常短。

 

# 问:deamon=True时 程序从FlagA执行到FlagB的时间大致为多少秒?并简述为什么?(2分)

0秒左右,如果设置deamon=True那么相当于开启了一个守护线程,守护线程会等待主线程结束之后才结束,而主线程会等待所有非守护线程子线程结束之后才结束,在程序中没有其他的非守护线程的子线程,因此主线程的代码结束之后守护线程就会立即结束。

(2)

loop = int(1E7)

def _add(loop: int = 1):

    global number

    for _ in range(loop):

        number += 1

 

def _sub(loop: int = 1):

    global number

    for _ in range(loop):

        number -= 1

 

number = 0

ta = threading.Thread(target=_add, args=(loop,))

ts = threading.Thread(target=_sub, args=(loop,))

ta.start()

ts.start()

ta.join()

ts.join()

# 问此时的number是否一定为零?并简述为什么?(2分)

不一定,因为在CPU指令中,+=操作是被拆分为两条指令的,所以可能出现数据不安全的情况。

(3)

number = 0

ta = threading.Thread(target=_add, args=(loop,))

ts = threading.Thread(target=_sub, args=(loop,))

ta.start()

ta.join()

ts.start()

ts.join()

# 问此时的number是否一定为零?并简述为什么?(2分)

会,如果加上join就使得代码从异步变成同步了,一定不会发生数据不安全的问题。 

(4)

loop = int(1E7)

 

def _add(loop: int = 1):

    global numbers

    for _ in range(loop):

        numbers.append(0)

 

def _sub(loop: int = 1):

    global numbers

    for _ in range(loop):

        while not numbers:

            time.sleep(1E-8)

        numbers.pop()

 

numbers = [0]

ta = threading.Thread(target=_add, args=(loop,))

ts = threading.Thread(target=_sub, args=(loop,))

ta.start()

ts.start()

ta.join()

ts.join()

# 问此时的numbers的长度是否一定为1?并简述为什么?(2分)

一定为1,因为列表的append操作是线程安全的。

 (5)

numbers = [0]

ta = threading.Thread(target=_add, args=(loop,))

ts = threading.Thread(target=_sub, args=(loop,))

ta.start()

ta.join()

ts.start()

ts.join()

# 问此时的numbers的长度是否一定为1?并简述为什么?(2分)

以上是关于练习题的主要内容,如果未能解决你的问题,请参考以下文章

csharp Epicor标准练习片段

golang 去练习片段

ktor HTTP API 练习

小片段中的 ORA-06512 [重复]

指针练习:输出Hello

片段着色器中未使用纹理数据 - OpenGL