Python面試題基礎部分(附答案)


必答題

1,簡述列舉了解的編程語言及語言間的區別?

Python 解釋型語言,代碼簡潔,易懂 C語言 編譯型語言,底層語言 c++ 編譯型語言,在C語言基礎上加了面向對象 Java 混合型語言,可拓展性高 Golang 編譯型語言,強類型,代碼規范,高並發 語言特點: 靈活簡潔,語言優美 可讀性強, 語言類型: 解釋型:逐行轉化,運行效率低,性能差,開發效率高。兼容性好,跨平台 編譯型 :一次性編譯成二進制文件,執行效率高,兼容性差, 動態語言:不用聲明變量的數據類型(腳本類語言) 靜態語言:需要聲明變量的數據類型 第三方庫:python定位是任其發展,開源庫很多,應用領域廣

2,列舉Python2和Python3的區別?

python2只更新支持到2020年 print:2不加括號,3加括號 input:2中用戶輸入解析為int類型,raw_input為字符串類型,3直接是字符串類型 range:2是列表,xrange是可迭代對象;3是可迭代對象 繼承關系:2是新式類+經典類;3是新式類 數字表示:2,int和long(長整形,超出2**63-1,數字末尾有一個L);3所有整型都是int

3,看代碼寫結果

v1 = 1 or 2 v2 = 3 and 3 or 9 and 0 # v1 = 1 # v2 = 7
# 邏輯運算符優先級 () > not > and > or # 邏輯短路
and 全真則真,一假則假 or 一真則真,全假則假 True or 表達式  => True (單個運算符和多個運算符的情況,都可以直接判定結果) False and 表達式 => False(單個運算符的時候可以) # 布爾值為假的十種情況: bool() => False
    0,0.0,False,0j,'',[],(),set(),{},None
詳解

4,以下的值有什么不同?

v1 = [1,2,3] v2 = [(1),(2),(3)] v3 = [(1,),(2,),(3,)] """ # 逗號才是區分是否是元組的標識符 v1 = [1,2,3] # 列表[int , int , int] v2 = [(89),(2.12),("abc")] # [int , float , str] v3 = [(1,),(2,),(3,)] # [tuple,tuple,tuple,tuple] res = () # 表達空元組 """

5,用一行代碼實現數值交換。

a = 1 b = 2 a,b = b,a # 通用
tmp = a a = b b = tmp

6,Python中單引號、雙引號、三引號的區別?

單雙引號沒有區別,三引號可以支持跨行
在互相嵌套時需注意:里外不能使用相同的引號

7,is和==的區別?

is 是判斷內存地址是否一致 == 是判斷兩個對象的值是否相等

8,python里如何實現tuple和list的轉化?

list(數據) tuple(數據)

9,如何實現字符串 st='愛吃大西瓜'的反轉?

st = st[::-1]

10,兩個set如何獲取交集、並集、差集?

交集 & intersection 差集 - difference 並集 | union 對稱差集 ^ symmetric_difference

11,那些情況下, y != x - (x-y)會成立?

非空集合且不為子父關系的兩個集合

12,Python中如何拷貝一個對象?

# copy模塊
[:] import copy copy.copy() # 淺拷貝
copy.deepcopy() # 深拷貝

13,簡述 賦值、淺拷貝、深拷貝的區別?

賦值:將變量和值在內存中形成映射指向關系
淺拷貝:只拷貝第一層元素地址copy.copy
深拷貝:為所有層級的元素都單獨開辟新空間 copy.deepcopy() (地址:原不可變數據只是暫時的指向,可變的數據獨立開辟新空間)

可變數據: list set dict
不可變數據: int float bool complex str tuple

14,pass的作用?

pass  占位符  與  ...的用法一樣

15,閱讀代碼寫結果:

import copy a = [1,2,4,5,['b','c']] b = a c = copy.copy(a) d = copy.deepcopy(a) a.append(5) a[4].append('d') print(b) # [1,2,4,5,['b','c','d'],5]
print(c) # [1,2,4,5,['b','c','d']]
print(a) # [1,2,4,5,['b','c','d'],5]

16,用Python實現9 * 9 乘法表。

# while
i = 1
while i<=9: # 這個位置寫代碼
    j = 1
    while j<= i: # "誰"*"誰"="誰"
        print("%d*%d=%2d" % (i,j,i*j),end=" ") j+=1
        
    # 打印換行
    print() i+=1

# for
for i in range(1, 10): for x in range(1, i + 1): print(f"{i} * {x} = {i * x}",end=" ") print("")

17,用Python顯示一個斐波那契數列。

# 1 1 2 3 5 8 13 21 ... # 方法一
lst = [1,1] for i in range(10): lst.append(lst[-1] + lst[-2]) print(lst) # 方法二
a,b = 0,1
for i in range(10): print(b) a,b = b,a+b # 方法三
def fib(n): if n <= 2: return 1
    # 上一個值 + 上上個值
    return fib(n-1) + fib(n-2) print(fib(6))

18,如何刪除列表中重復的值?

list(set(list))

19,一個大小為100G的文件etl_log.txt, 要讀取文件中的內容, 寫出具體過程代碼?

with open(r'etl_log.txt','r',enconding='utf-8') as f: for i in f: info = f.readlines() print(info) fp = open("文件名","模式","編碼集") """ fp 是迭代器 from collections import Iterator,Iterable # 在遍歷fp時,文件按照一行一行進行讀取; for i in fp: code ... """

20,a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) 請問a是什么?

a為字典
強轉字典的條件:等長的二級容器,配合強轉字典的兩個函數 zip , enumerate # zip 拉鏈
a = dict( zip( ("a","b") , [1,2] ) ) print(a) # enumerate 枚舉
a = dict( enumerate( ["a","b"] )) a = dict( enumerate( ["a","b"] ,start = 10 )) print(a)
詳解

21,lambda關鍵字的作用?

lambda 匿名函數 : 用一句話表達只有返回值的無名函數 lambda 參數 : 返回值

22,*arg和**kwarg作用?

*args 接收多余的位置參數 **kwargs 接收多余的關鍵字參數

23,如何在函數中設置一個全局變量 ?

global 有該全局變量,修改當前變量,沒有改全局變量,定義一個全局變量; """ def func(): global a a = 90 func() print(a) """

24,filter、map、reduce的作用?

三目(元)運算符  True   if 條件表達式 else False filter => 過濾數據 iterable : 可迭代對象(range ,容器類型數據 , 迭代器) filter(func,iterable) => 返回迭代器 lst = [1,2,3,4,5] it = filter(lambda x : True   if x % 2 == 0 else False , lst ) print(list(it))

25,什么是匿名函數?匿名函數有什么作用?

lambda 匿名函數 : 用一句話表達只有返回值的無名函數 lambda 參數 : 返回值

26,Python遞歸的最大層數?

官方:1000 實測:994 ~ 1000

import sys sys.setrecursionlimit(999999) # 修改遞歸的最大深度,mac能達到30000

27,什么是迭代器?什么是可迭代對象?

迭代器:具有__iter__()和__next__()方法 可迭代對象:具有__iter__()方法 dir(數據) 可以查看該數據的內部系統成員 可迭代對象 => 迭代器  把不能直接被next獲取 => 可直接獲取到該數據的一個過程

28,什么是生成器?

生成器的本質就是迭代器,可以自定義迭代的邏輯 創建方式兩種: (1)生成器表達式 (推導式)  (i for i in range(3)) (2)生成器函數   (含有yield關鍵字)

29,什么是裝飾器及應用場景?

裝飾器的本質就是閉包 在不修改原有代碼的前提下,額外增加新功能就是裝飾器 應用:登錄認證,property類,框架(django,flask,@app.route("/",methdos=["GET","POST"]))

30,什么是反射及應用場景?

# 通過字符串去操作類對象 或者 模塊中的屬性方法
 hasattr getattr setattr delattr 應用: 可以配合用戶的操作或者輸入,調用其中的成員,api接口中

31,寫一個普通的裝飾器。

def wrapper(func): def inner(*args,**kwargs): res = func(*args,**kwargs) print("and you") return res return inner @wrapper def func(): print("i am fine 3q") func()

32,寫一個帶參數的裝飾器。

def outer(n): def wrapper(func): def inner1(*args,**kwargs): res = func(*args,**kwargs) print("我是大王") return res def inner2(*args,**kwargs): res = func(*args,**kwargs) print("大王叫我來巡山") return res if n == "alex": return inner1 else: return inner2 return wrapper @outer("alex123") # outer("alex123") => wrapper =>@wrapper
def func(): print("i am fine 3q") func()

33,求結果:

def num(): return [lambda x:i*x for i in range(4)] print([m(2) for m in num()])
[6,6,6,6]
""" def出現的位置是函數的定義處 函數() 出現的位置是函數的調用處 (1)調用的時候,才會把函數中的代碼,從上到下執行一遍,否則不執行 (2)里面的func是一個閉包函數,延長了當前變量i的生命周期,最后一次i的值3,所以再去調用時候拿的3 """
詳解

34,def(a, b=[])這種寫法有什么陷阱?

b身上的默認值是列表,如果使用原來默認的參數,調用func函數
會把幾次調用的值都存放在同一個默認列表里
""" 默認參數: 如果調用時,用戶給實參了,那么使用用戶的 如果調用時,用戶沒給實參,那么使用默認的(早已存在內存中的這個列表) 默認值會提前在內存中駐留,在使用時,才能調取,在定義函數的時候就提前開辟了空間 """
詳解

35,看代碼寫結果

def func(a,b=[]): b.append(a) return b v1 = func(1) v2 = func(2,[10,20]) v3 = func(3) print(v1,v2,v3)
[1,3],[10,20,2],[1,3]

36,看代碼寫結果

def func(a,b=[]): b.append(a) return b v1 = func(1) print(v1) v2 = func(2,[10,20]) print(v2) v3 = func(3) print(v3)
[1] [10,20,2] [1,3]

37,請編寫一個函數實現將ip地址換成一個整數。

如 10.3.9.12 轉換規則為: 10 00001010
3 00000011
9 00001001
12 00001100 再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 = ?
# ljust 原字符串居左,填充符號 # rjust 原字符串居右,填充符號 # 方法一
ip = "10.3.9.12" strvar = ""
for i in ip.split("."): bin_str = str(bin(int(i)))[2:] # 總長度是8 原字符串居右
    strvar += bin_str.rjust(8,"0") print(strvar) # 把二進制字符串轉換成十進制,默認轉換時,是十進制
print(int(strvar,2)) # 方法二
ip = "10.3.9.12" strvar = ""
for i in ip.split("."): # format 將整型轉化成二進制,不夠8位的拿0補位
    strvar += format(int(i) , "08b") print(int(strvar,2))

38,請查找一個目錄下的所有文件(可能存在文件嵌套)

# 方法一 (遞歸寫法)
import os def getallsize(pathvar): size = 0 lst = os.listdir(pathvar) print(lst) for i in lst: pathvar2 = os.path.join(pathvar,i) print(pathvar2) # 判斷是否是文件
        if os.path.isfile(pathvar2): size += os.path.getsize(pathvar2) # 判斷是否是文件夾
        elif os.path.isdir(pathvar2): size += getallsize(pathvar2) print(size) return size # "E:\串講基礎\day2\test\1.txt"
pathvar = r"E:\串講基礎\day2\test" res = getallsize(pathvar) # print(res)

# 方法二
import os # os.walk() => 生成器
pathvar = r"D:\Reptile\PycPc" gen = os.walk(pathvar) for root, dirs, files in gen: for name in files: pathvar = os.path.join(root, name) print(pathvar)

39,求結果:

import math print (math.floor(5.5))
5
""" floor 地板除 ceil 天花板除 round round n.5 奇進偶不進 print(round(4.5)) 4 print(round(5.5)) 6 print(round(4.52)) 5 """
拓展

40,是否使用過functools中的函數?其作用是什么?

wraps    # 在裝飾器中使用,如果想要保留原來函數的屬性,加上wraps
 reduce # 累計算
# 在裝飾器中使用,如果想要保留原來函數的屬性,加上wraps
from functools import wraps def wrapper(func): @wraps(func) def inner(*args, **kwargs): res = func(*args, **kwargs) print("and you") return res return inner @wrapper def func(): print("i am fine 3q") func() print(func) # def abc(): # pass # print(abc)
詳解

41,re的match和search區別?

match:    從開頭進行查找,查找到就停止,找不到返回None
search: 查找全文,找到就停止,找不到就返回None

42,用Python匹配HTML tag的時候,<.*><.*?>有什么區別?

.* 貪婪匹配 匹配多個任意字符 .*? 非貪婪 只匹配一次

43,如何生成一個隨機數?

import random random.random() # 生成隨機小數,0<= x < 1

44,super的作用?

# 用來解決多繼承之間復雜的調用關系使用super
在多繼承中, 如果出現了多個同名方法 super在調用的時候, 會按照mro列表的繼承順序依次調用 類.mro() = > lst
詳解

45,雙下划線和單下划線的區別?

雙線划線:__ 是Python中強制定義為私有
單下划線:_  是程序員約定的私有方法

46,@staticmethod和@classmethod的區別?

一個靜態方法, 一個類方法
一個靜態方法: (無論是對象還是類, 都可以調用, 不會默認傳遞任何參數)
一個類方法: (無論是對象還是類, 都可以調用, 會默認傳遞類這個參數)

47,實現一個單例模式(加鎖)

from threading import Lock class MyClass(object): __obj = None lock = Lock() def __new__(cls, *args, **kwargs): with cls.lock: if not cls.__obj: cls.__obj = object.__new__(cls) return cls.__obj obj1 = MyClass() obj2 = MyClass() print(obj1, obj2)

48,棧和隊列的區別?

棧:先進后出,或者后進先出
隊列:先進先出

49,一下代碼輸出是什么?請給出答案並解釋。

class Parent(object): x = 1
class Child1(Parent): pass
class Child2(Parent): pass
print Parent.x, Child1.x, Child2.x Child1.x = 2
print Parent.x, Child1.x, Child2.x Parent.x = 3
print Parent.x, Child1.x, Child2.x
""" 1,1,1 兩個child都繼承了parent,並沒有自己的屬性或方法 1,2,1 child1添加了屬性,就近原則使用自己x的值,child2沒有,繼承父類 3,2,3 parent和chile1有自己的x方法,就近使用自己的,chiild2沒有自己的x,繼承父類中的x """

50,參考下面代碼片段:

class Context: pass with Content() as ctx: ctx.do_something() 請在Context類下添加代碼完成該類的實現
class Context(): def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): # 相當於在最后,執行了文件的關閉操作,fp.close()
        print("abc123") def do_something(self): print(1111) with Context() as ctx: ctx.do_something() print(ctx) # 自動實現了關閉操作 # with open("文件") as fp: # res = fp.read()

可選題

1,如何獲取列表中第二大的值?

# 去重
lst = set([98,1,100,3,-100,50,100,100]) res = sorted(lst) res_new = res[-2] print(res_new)

2,簡述Python內存管理機制。

計數器,垃圾回收,內存池 # 一.計數器
特點:引用技術如果是0,把這個值從內存中釋放掉 缺點:在維護引用計數時,又可能數據產生循環引用,造成數據不能刪除,造成內存泄漏 # 二.垃圾回收:引用計數為主,標記清除和分帶回收為輔
標記清除 : 檢測標記該對象,避免出現循環引用不能刪除的現象 分帶回收 : 把內存中的數據分成三個區域: 新生代0,老年代1,永久代2 新生代0數據超過700 , 或者老年代1,永久代2數據超過10,自動觸發內存中的垃圾回收機制 新生代0觸發將清除所有三代的區域 老年代1觸發會清理1,2代 永久代2觸發只會清理自己 # 三.內存池 # 在同一個文件當中 (python3.6) # -->Number 部分
    1.對於整型而言,-5~正無窮范圍內的相同值 id一致 2.對於浮點數而言,非負數范圍內的相同值 id一致 3.布爾值而言,值相同情況下,id一致 4.復數在 實數+虛數 這樣的結構中永不相同(只有虛數的情況例外) # -->容器類型部分
    5.字符串 和 空元組 相同的情況下,地址相同 6.列表,元組,字典,集合無論什么情況 id標識都不同 [空元組例外] # 在不同的文件當中
    小數據池 ; 比如整型默認開辟 -5~256 這么多數據提前在內存中駐留

3,簡述Python的垃圾回收機制。

垃圾回收:引用計數為主,標記清除和分帶回收為輔
標記清除 : 檢測標記該對象,避免出現循環引用不能刪除的現象
分帶回收 :
    把內存中的數據分成三個區域: 新生代0,老年代1,永久代2
    新生代0數據超過700 , 或者老年代1,永久代2數據超過10,自動觸發內存中的垃圾回收機制
    新生代0觸發將清除所有三代的區域
    老年代1觸發會清理1,2代
    永久代2觸發只會清理自己

4,請用兩個隊列來實現一個棧。

""" 棧 : 先進后出,后進先出 隊列 : 先進先出,后進后出 """
from queue import Queue class Stack(): def __init__(self): self.master_queue = Queue() self.minor_queue = Queue() def push(self, val): # 入棧
 self.master_queue.put(val) def pop(self): # 出棧
        # 如果隊列中沒有任何值,直接返回None
        if self.master_queue.qsize() == 0: return None while True: # 當隊列總長度為1的時候,循環終止,把最后一個元素拿出來,為了滿足棧后進先出的特點
            if self.master_queue.qsize() == 1: value = self.master_queue.get() break

            # 剩下還沒有拿出來的元素,暫時放在2號隊列中存儲
 self.minor_queue.put(self.master_queue.get()) """ minor_queue(1) master_queue(2 3 4) minor_queue(2) master_queue(3 4) minor_queue(3) master_queue(4) """
        # 交換隊列,重新循環,繼續去最后一個值,如法炮制
        self.master_queue, self.minor_queue = self.minor_queue, self.master_queue return value obj = Stack() obj.push("a") obj.push("b") obj.push("c") print(obj.pop())  # c
print(obj.pop())  # b
print(obj.pop())  # a
print(obj.pop())  # a

5,請用Python實現一個鏈表。

class Node(): def __init__(self, value, next): self.value = value self.next = next head = Node("", None) last = head for i in range(5):  # v0 v1 v2 v3 v4
    node = Node("v%s" % i, None) last.next = node last = node # 查看鏈表的關系
print(head.value) print(head.next.value) print(head.next.next.value) print(head.next.next.next.value) print(head.next.next.next.next.value) print(head.next.next.next.next.next.value) # print(head.next)
print("<========>")

6,請用Python實現鏈表的逆轉。

def reverse_link_list(head): # 要是空的,或者None,直接返回head
    if not head or not head.next: return head # 獲取上一個節點對象
    prev_node = None # 獲取下一個節點對象
    next_node = head.next # 獲取當前節點對象
    current_node = head while True: # 修改next,所指向的對象
        current_node.next = prev_node # 如果下一個階段對象是None
        if not next_node:  # not None
            break

        # 重新獲取上一個對象,即把當前丟向單獨存一份,以准備第二次循環時插進next屬性中
        prev_node = current_node # 重新獲取當前對象 , 即把下一個對象單獨存儲起來(下個)
        current_node = next_node # 重新獲取下一個對象,即把下一個對象單獨存儲起來,所指向的下個新對象賦值給next_node(下下個)
        next_node = current_node.next return current_node head = reverse_link_list(head) print(head.value) print(head.next.value) print(head.next.next.value) print(head.next.next.next.value) print(head.next.next.next.next.value) print(head.next.next.next.next.next.value)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM