新筆記 python 面試

鸟叔书發表於2024-06-07

1.python 的資料型別(可變和不可變)
1).可變資料型別:
列表 list
字典 dict
集合 set
2).不可變型別:
整型 int
字串 str
浮點型 float
元組 tuple
數值型別 如:複數 complex
布林型別 bool

2.python 的去重排序

1).去重 set:

        numbers = [1, 2, 2, 3, 4, 4, 5]
        unique_numbers = list(set(numbers))
        print(unique_numbers)

2).排序 Sorting:

            sorted():
                sorted()函式可以對任何可迭代物件進行排序,返回一個新的排序後的列表,原列表保持不變。
                numbers = [5, 9, 1, 4, 3]
                sorted_numbers = sorted(numbers)
                print(sorted_numbers)

            使用列表的.sort()方法:
                與sorted()不同,列表的.sort()方法直接在原列表上進行排序,不返回新的列表。
                numbers = [5, 9, 1, 4, 3]
                numbers.sort()
                print(numbers)

3.python的記憶體管理
1)自動垃圾回收:
Python 直譯器會追蹤物件的引用計數,一個物件的引用計數變為0時,說明沒有任何變數指向該物件,直譯器就會回收這塊記憶體。

2)引用計數:
Python 內部為每個物件維護一個引用計數,表示有多少個變數或資料結構引用了這個物件。當物件被建立時,其引用計數初始化為1;當物件被一個新的變數引用時,引用計數增加;當變數不再引用該物件或被重新賦值時,引用計數減少。當引用計數減到0時,物件就可以被銷燬並回收其佔用的記憶體。

3)迴圈引用收集:
僅依賴引用計數機制有時無法處理迴圈引用的問題,即兩個或多個物件互相引用形成一個閉環,但這些物件實際上已經不再被程式其他部分使用。為解決這個問題,Python 引入了週期檢測機制,週期性地檢查並打破這些迴圈引用,從而能夠回收這些物件佔用的記憶體。

4)分代垃圾回收:
Python 的垃圾回收機制將物件分為不同的“代”。新建立的物件歸入年輕代,如果經歷過一定次數的垃圾回收後仍然存活的物件會被移動到老年代。老年代的物件不常進行回收,因為它們更可能是長時間存活的物件。這種策略基於觀察到的大多數物件很快變得不可達的規律,減少了垃圾回收的開銷。

5) 記憶體池:
為了減少對作業系統分配和釋放小塊記憶體的呼叫(這通常比較耗時),Python 使用記憶體池技術預先向作業系統申請一大塊記憶體,並在此基礎上進行小塊記憶體的分配和回收,提高了記憶體分配的效率。

4.python 執行緒與程序
1) 執行緒:
執行緒是程序內的執行單元,是CPU排程的基本單位。同一程序內的多個執行緒共享該程序的記憶體空間和資源,但每個執行緒有自己的程式計數器、堆疊和區域性變數。
優勢:
輕量級:相比程序,執行緒的建立和切換開銷較小。
通訊簡便:因為共享同一地址空間,執行緒間可以直接訪問同一程序內的資料,通訊更為直接快速。
劣勢:
資源共享問題:多個執行緒訪問共享資源可能導致資料不一致,需要使用鎖、訊號量等同步機制來避免競態條件。
可靠性:一個執行緒崩潰可能會影響到同一程序內的其他執行緒。

2) 程序:
程序是作業系統資源分配的基本單位,每個程序都有獨立的記憶體空間、程式碼段、資料段、堆疊等,因此,程序之間的資料是隔離的。建立和切換程序的開銷比較大,因為涉及到作業系統級別的資源分配。
優勢:
獨立性:程序之間相互獨立,一個程序崩潰不會影響其他程序。
資源隔離:每個程序有自己獨立的資源,適合執行大量且長時間執行的任務。
劣勢:
開銷大:建立和銷燬程序,以及程序間的通訊成本較高。
通訊複雜:由於程序間地址空間隔離,程序間通訊相對複雜,常用管道、套接字、共享記憶體等機制。

3) 選擇原則:
如果你的任務需要大量的計算或者需要獨立的記憶體空間,且任務之間關聯不大,可以考慮使用多程序。
如果你的任務主要是I/O密集型(如網路請求、檔案讀寫),或者需要頻繁的資料交換,使用多執行緒可能會更高效。
對於CPU密集型任務且需要利用多核處理器,可以結合使用多程序和執行緒,根據具體場景選擇合適的併發模型。
在 Python 中,可以透過multiprocessing模組來建立和管理程序,透過threading模組來建立和管理執行緒。

5.邏輯運算子的優先順序:
() > not > and > or

6.python常用的模組:
1) os提供了許多與作業系統互動的函式,如檔案操作、程序管理等。
2) sys:提供訪問和使用 Python 直譯器的一些功能,比如命令列引數、退出程式等。
3) math:包含數學相關的函式,如平方根、對數、三角函式等。
4) datetime:處理日期和時間,包括日期/時間的運算和格式化。
5) json:用於編碼和解碼 JSON 資料,方便與 Web 服務互動。
6) re:正規表示式模組,用於文字模式匹配和替換。
7) requests:一個非常流行的第三方庫,用於傳送 HTTP 請求,非常適合網路爬蟲和API呼叫。
8) BeautifulSoup 和 lxml:這兩個庫常用於網頁解析,提取 HTML 或 XML 頁面中的資料。
9) pandas:資料分析領域的明星庫,提供了高效的資料結構DataFrame,以及資料分析工具。
10) numpy:基礎科學計算包,提供了高效能的多維陣列物件和數學函式。
11) matplotlib 和 seaborn:用於資料視覺化,建立靜態、動態、互動式的圖表。
12) flask 和 django:兩個非常流行的Web框架,用於快速開發web應用。
13) sqlalchemy:SQL工具包和ORM系統,用於資料庫操作。
14) unittest:Python標準庫中的單元測試框架,用於編寫測試用例。
15) logging:日誌記錄模組,幫助開發者記錄程式執行過程中的資訊。

  1. python程式會記憶體溢位嗎?
    Python 程式確實有可能發生記憶體溢位。記憶體溢位指的是程式執行過程中消耗的記憶體超過了系統分配給它的可用記憶體空間,導致程式無法正常執行或崩潰。
    Python 自帶的記憶體管理機制,如自動垃圾回收和引用計數等,通常能有效避免一些常見的記憶體洩漏問題,但這並不意味著程式完全不受記憶體限制。以下幾種情況可能導致 Python 程式出現記憶體溢位:

    1)無限增長的資料結構:
    如果程式中存在不斷增長的資料結構(如列表、字典等),並且增長速度超過了垃圾回收機制處理的速度,最終可能會耗盡記憶體。
    2)迴圈引用:
    雖然 Python 的垃圾回收器能夠處理大多數迴圈引用問題,但在某些複雜情況下,尤其是涉及大量物件的迴圈引用,也可能導致記憶體洩露,進而引發記憶體溢位。
    3)大檔案處理不當:
    一次性讀取非常大的檔案到記憶體中,或者不當的檔案處理邏輯,都可能導致記憶體使用激增。

    4)第三方庫的記憶體洩漏:
    使用第三方庫時,如果庫內部存在記憶體洩漏問題,也可能導致程式記憶體使用持續增長。

    5)系統資源限制:
    作業系統對每個程序可使用的記憶體大小有限制。即使Python程式理論上還有足夠的記憶體可供使用,但如果超過了作業系統的限制,也會觸發記憶體溢位錯誤。
    採取措施:
    memory_profilertracemalloc 等工具分析記憶體使用情況,定位記憶體消耗高的部分。
    最佳化資料結構和演算法,避免不必要的記憶體佔用。
    分批處理大資料,避免一次性載入過多資料到記憶體中。
    使用生成器 (generator) 來處理大檔案或大量資料流。
    對於極端情況,可能需要考慮使用分散式計算框架來分散處理任務,減輕單機記憶體壓力。

8.python裝飾器:
python裝飾器是一種非常有用的功能,它允許使用者在不修改原始函式的情況下,給函式新增額外的功能。
裝飾器本身是一個接收函式作為引數的可呼叫物件並返回一個新的函式,這個新函式通常會在執行原始函式之前或之後增加一些額外的操作。

基本語法:
    裝飾器的定義通常使用`@decorator_name`語法糖,放在函式定義之前。下面是一個簡單的裝飾器示例,該裝飾器用於列印函式被呼叫的資訊:         
            def my_decorator(func):
                def wrapper():
                    print(f"{func.__name__} is being called")
                    func()
                return wrapper

            @my_decorator
            def say_hello():
                print("Hello!")

            say_hello()

9.python中local對像和Threading.local物件的區別

    在Python中,`local`物件並沒有直接作為官方術語使用,但我們可以將其理解為一般意義上的區域性變數,即在一個函式、方法、類定義或lambda表示式內部宣告的變數,其作用域僅限於該定義內部。區域性變數對於函式外部是不可見的,且不同函式呼叫之間的區域性變數互不影響,不提供跨函式或跨執行緒的資料共享。

    而`threading.local`物件是Python標準庫`threading`模組中提供的一個特殊型別,用於建立執行緒本地儲存。它允許每個執行緒擁有該物件屬性的獨立副本,從而實現了執行緒間資料的隔離。這意味著,即使多個執行緒訪問同一個`threading.local`例項的屬性,每個執行緒看到和修改的都是該屬性的一個執行緒特有的版本,不會發生資料衝突。
總結兩者之間的區別:
    
    1) 作用域:
        `local`(區域性變數):作用域侷限於定義它們的函式、方法、類或lambda表示式內部,是程式碼執行的基本範圍限制。
        `threading.local`物件:作用於整個執行緒生命週期,跨越函式呼叫,為每個執行緒提供獨立的資料檢視。

    2) 資料共享與隔離:
        `local`(區域性變數):天然隔離,每個函式呼叫或程式碼塊執行都有自己的獨立副本,不涉及跨執行緒資料共享。
        `threading.local`物件:提供了執行緒間的資料隔離機制,即使在全域性範圍內使用,也能確保每個執行緒只能訪問到自己的資料副本,非常適合儲存執行緒特有的狀態資訊。

    3) 應用場景:
        `local`(區域性變數):用於控制變數的可見性和生命週期,是最基本的變數作用域概念。
        `threading.local`物件:適用於多執行緒程式設計中需要維護執行緒特有資料的場景,如資料庫連線、會話資訊或執行緒區域性快取等。

10.Lambda函式

lambda函式是Python中一種簡潔的、快速定義單行、小型匿名函式的方法。“匿名”意味著它沒有具體名稱,這與常規的有名的函式不同。lambda函式常用於需要短暫使用的簡單功能場合,尤其是高階函式(如`map()`、`filter()`、`sorted()`等)的引數中,或者作為字典的值等場景。
Lambda函式基本語法如下:
    lambda arguments: expression
    `lambda` 是關鍵字,用來宣告這是一個lambda函式。
    `arguments` 是傳入lambda函式的引數列表,可以有一個或多個引數,引數之間用逗號分隔,且無需指定引數型別。
    `expression` 是一個表示式,計算後作為lambda函式的返回值。注意,lambda函式只能包含一個表示式,不能包含複雜的語句或賦值操作。
    
    double = lambda x: x * 2
    print(double(5))  # 輸出10

    sum = lambda x, y: x + y
    print(sum(3, 4))  # 輸出7

    sort_by_second_element = sorted([(1, 'b'), (2, 'a'), (3, 'c')], key=lambda x: x[1])
    print(sort_by_second_element)  # 輸出[(2, 'a'), (1, 'b'), (3, 'c')]

11.python迭代器
1)
在Python中,迭代器(Iterator)是一種特殊型別的物件,它能夠遍歷集合中 的元素,如列表、元組、字典、集合等。迭代器的主要優點是它允許你以一種統一的方式處理不同型別的可迭代物件,並且只在需要時載入元素,這在處理大量資料時非常有用,可以節省記憶體。
2)基本概念:
1. 可迭代物件(Iterable):任何可以直接作用於for迴圈的資料型別都是可迭代物件。比如,列表、字串、元組、字典、集合等。
2. 迭代器(Iterator):從可迭代物件中建立的,可以記住遍歷的位置,迭代器物件實現了__iter__()__next__()兩個方法。__iter__()返回迭代器本身,__next__()返回容器的下一個專案,當沒有更多專案時,引發StopIteration異常。
3)建立迭代器:
你可以使用iter()函式從一個可迭代物件建立一個迭代器:

    ```python
    my_list = [1, 2, 3]
    my_iterator = iter(my_list)
    ```
4)使用迭代器
    一旦建立了迭代器,就可以透過`next()`函式或在`for`迴圈中使用它來遍歷元素:

        ```python
        # 使用next()函式手動迭代
        print(next(my_iterator))  # 輸出: 1
        print(next(my_iterator))  # 輸出: 2

        # 或者在for迴圈中自動迭代
        for item in my_iterator:
            print(item)  # 輸出剩餘的元素
        ```

7. 面試問題:印象最深的,你處理的問題是什麼

排查思路:
a: 安全組是否開放 22 埠
b: eth0 是否有ip地址
c:是否能 ping 通
d: sshd 服務是正常 active/running
f: 配置檔案 ssh_config, sshd_config

排查用的工具或者排查檔案:
/var/log/secure
/etc/ssh/sshd_config
/etc/ssh/ssh_config
journalctl -u sshd

面試問題:系統無法啟動,卡死,一般怎麼排查,如何排查

排查思路:
a. 如果能進入單使用者,可以進入單使用者排查
b. 無法進入單使用者,那就掛 pe 排查
排查方法:
a. 透過 lsblk, blkid, /etc/fstab 檢視掛載是否是正確的 UUID
b. 檢查 /boot/grub2/grub.cfg 是否存在,配置是否正確
c. 檢視 /boot 目錄下檔案是否缺失
d. /etc/default/grub
f. grep -E "fail|err" /var/log/messages
g. journalctl | grep -E "fail|err"
h. 檢視串列埠日誌

3.專案:repo源監控

# 1. 提前準備好每個系統的repo檔案,拉取每個系統對應的docker映象
[root@kvm ~]# ls repo
01_centos-7-9      04_opensuse-15-5  07_alinux-2-1903  10_debian-11-8  13_fedora-37       16_almalinux-8-9
02_centosstream-9  05_almalinux-9-3  08_anolis-8-8     11_fedora-39    14_rockylinux-9-3  17_centosstream-8
03_ubuntu-22       06_alinux-3-2104  09_debian-12-4    12_fedora-38    15_rockylinux-8-9  18_ubuntu-20
[root@kvm ~]#
[root@kvm ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
centos       7         eeb6ee3f44bd   2 years ago   204MB

# 2. 啟動容器,做repo對映
docker run  -it --rm -v /root/repo/01_centos-7-9:/etc/yum.repos.d centos:7 /bin/bash

# 3.檢查裝包是否成功
[root@ecc485a034b0 /]# yum -y remove unzip
[root@ecc485a034b0 /]# yum -y install unzip
[root@ecc485a034b0 /]# echo $?   # echo "Err: centos 7.9 repo not work"
[root@ecc485a034b0 /]# rpm -qa | grep unzip
unzip-6.0-24.el7_9.x86_64

相關文章