python易錯點2


8. __init__函數內不可以使用return語句

Python規定__init__函數只能返回None,否則會引起TypeError

9. 在try…except…finally中return

  • try和except中return語句設定的返回值,可以在finally塊中被修改;
  • 實踐中不要在finally中使用return,這是一種不好的代碼,容易讓人產生疑惑。finally塊主要用於進行清理工作。

Python札記7:在try...except...finally中return

不論try語句塊中發生了什么異常,finally語句塊中的代碼都會被執行。所以我們通常在finally語句塊中做清理工作,例如關閉文件等等

請看下面的代碼,輸出是什么呢?

def f():
  try:
    return 1
  finally:
    print("hehe")

print(f())

  finally塊中的代碼必定執行,所以輸出如下:

 也就是說,雖然try中有return語句,但是退出try...finally塊之前,也一定會執行finally塊中的語句。

 

 

 

 

 

 

10. os.path的abspath()和realpath()區別

  • os.path.abspath 返回目標地址,會處理...等相對路徑,不處理軟連接和快捷方式
  • os.path.realpath 返回的是使用軟鏈的真實地址,它能在所有的平台上對所有別名、快捷方式以及符號鏈接進行一致地解析。
# 特殊的文件名,比如 “..” 會被移除,這樣輸入在驗證之前會被簡化成其標准形式。
當使用標准形式的文件路徑來做驗證時,攻擊者將無法使用 ../ 序列來跳出特定目錄

11. python中and與or的邏輯

首先,‘and’、‘or’和‘not’的優先級是not>and>or。

其次,邏輯操作符and 和or 也稱作短路操作符(short-circuitlogic)或者惰性求值(lazy evaluation):它們的參數從左向右解析,一旦結果可以確定就停止。例如,如果A 和C 為真而B 為假, A and B and C 不會解析C 。作用於一個普通的非邏輯值時,短路操作符的返回值通常是最后一個變量。因此,邏輯運算符的理解也與C語言中不同

a = {1, 2, 3} and {4, 5, 6}
b = {1, 2, 3} or {4, 5, 6}
print(a) # {4, 5, 6}
print(b) # {1, 2, 3}

其實python中and並不是直接返回True/False,而是返回比較的值,具體如下邏輯:
and:停止的目標為False, 如果有True,一直往下找,直到返回最后一個或者第一個False
or: 停止的目標為True,如果有False,一直往下找,直到返回最后一個或者第一個True

12. 字符串,bool,序列對象等都可以比較

1.2 > True  # True
1 > True  # False
bool('0')  # True

字符串也好,列表也好,都是可迭代對象。先比較兩個對象的第0個元素,大小關系即為對象的大小關系(字典序),如果相等則繼續比較后續元素,先終止迭代的認為是小的。序列對象通常可以與相同序列類型的其他對象比較。

[1,5]<[3,4,6] # True
[1,4,[5,6]]<[3,4,6] # True
[3,4,[5,6]]<[3,4,6] # TypeError: '<' not supported between instances of 'list' and 'int'

13. 字符串格式化

 https://blog.csdn.net/qq_27825451/article/details/105652244

14. @classmethod與@staticmethod

 Python中的類也是一個普通對象,如果需要直接使用這個類,例如將類作為參數傳遞到其他函數中,又希望在實例化這個類之前就能提供某些功能,那么最簡單的辦法就是使用classmethod和staticmethod。這兩者的區別在於在存在類的繼承的情況下對多態的支持不同。

類方法的作用:(不依賴於對象)

因為只能訪問類屬性和類方法,所以,可以在對象創建之前如果需要做一些功能(動作),就可以放在類方法中

私有屬性只能通過類方法,在類內部進行訪問

靜態方法:很類似類方法

1.需要裝飾器@staticmethod

2.靜態方法是無需傳遞參數(如,cls,self)

3.靜態方法里面也只能訪問類的屬性和方法,而對象的屬性和方法是無法訪問的(即,用self.xx訪問屬性和訪問方法是不可以的)

4.加載時機同類方法,即在對象還沒有創建時,就已經加載了

class Spam(object):
    numInstances = 0
 
    @staticmethod
    def count():
        Spam.numInstances += 1
 
    def __init__(self):
        self.count()
 
 
class Sub(Spam):
    numInstances = 0
 
 
class Other(Spam):
    numInstances = 0
 
 
x = Spam()
y1, y2 = Sub(), Sub()
z1, z2, z3 = Other(), Other(), Other()
# 對象調用
print(x.numInstances, y1.numInstances, z1.numInstances)
# 類調用
print(Spam.numInstances, Sub.numInstances, Other.numInstances)

  

 總共六次加載對象,靜態方法在對象還沒有創建之前就已經加載了了,因此x.numInstances=6,而另外兩個是Spam的子類,創建對象后,又執行了y1.numInstances,y2.numInstances,因此,y1.numInstances=0,y2.numInstances=0

Spam.numInstances, Sub.numInstances, Other.numInstances分別是訪問它們類的屬性

 

 

https://www.cnblogs.com/GumpYan/p/12381705.html

15. 防范會話固定,應采取以下步驟:

  • 登錄時,使當前會話無效,並建立一個新的會話。
  • 不要接受以GET 或POST參數方式提交的會話 ID,包括隱藏的表單變量。
  • 在所有cookie上設置HttpOnly屬性為true,以防范腳本讀取cookie內容。
  • 在所有cookie上將Secure(安全)屬性設置為true,使其只能通過TLS連接發送。
  • 在會話cookie上設置合理的失效日期。

15.1 系統環境變量是屬於“不可信數據”,直接使用不可信數據可能會引入安全風險

import  os
home = os.getenv('APPHOME')
cmd = os.path.join(home, INITCMD)
os.system(cmd)

  其中環境變量APPHOME對應的路徑是可修改的,直接使用會造成安全風險。

16. shell命令

Subprocess安全

subprocess模塊的用法, run/Popen/call/check_call/check_output 在使用時指定shell參數為False時,都會存在命令注入缺陷。(第一個參數禁止使用cmd/bash
切記第1個參數中的list列表的第一個元素不允許是“bash”、“cmd”、“/bin/sh第二個元素不允許是“-c;只有滿足了這兩個前提條件,參數shell=True情況才是安全的。

subprocess模塊的用法, Popen/call/check_call/check_output 在使用時指定shell參數為False時,都會存在命令注入缺陷。(第一個參數禁止使用cmd/bash,第二個元素不允許是“-c”)。如果不可避免的要設置shell為true,應將命令作為單一字符串傳遞,並使用shelx.quote()手動轉義所有shell元字符。

Python安全編程規范V2.1

規則 1.8 禁止使用subprocess模塊中的 shell=True選項

 

 

 subprocess模塊中的 shell=Flase場景的第1個參數為什么不能是cmd/bash/sh等系統命令

17. 隨機數的安全

根據安全規范6.5:
os.urandom在windows系統中生成的隨機數是安全的,在linux系統環境中生成的隨機數不安全。
random模塊生成的是偽隨機數,不能應用於安全加密目的的應用中
安全隨機數可以使用:/dev/random,Python3.6以上的secrets模塊

18. 全局常量用全大寫,全局變量用小寫

19. 避免直接使用dict[key]的方式從字典中獲取value

如果一定要使用,需要注意當key not in dict時的異常捕獲和處理。應始終使用get,即dict.get(key),而不是dict[key]

20. 避免變量在其生命周期內的對象類型發生變化。

如:

items = 'a,b,c,d' # 字符串
items = items.split(',') # 變更為列表

21. 驗證路徑之前應該先將其標准化

使用os.path.realpath('test') 而非os.path.abspath('test')。 Path().resolve()好像類似。

22. Server端發起網絡請求前要驗證是否存在SSRF漏洞。

SSRF(Server-SideRequest Forgery, 服務端請求偽造)

應該先對url做ssrf校驗

url = sys.argv[1]
try:
    info = urllib.request.urlopen(url).info()
    print(info)
except urllib.error.URLError as e:
    print(e)

規避SSRF漏洞的思路:

  1. 解析目標URL,獲取其Host
  2. 解析Host,獲取Host指向的IP地址
  3. 檢查IP地址是否為內網IP
  4. 請求URL
  5. 如果有跳轉,拿出跳轉URL,回到第1步循環此過程

23. 禁止使用tempfile.mktemp創建臨時文件

使用tempfile.mkstemp()NamedTemporaryFile()mkdtemp(), 而非tempfile.mktemp()

24. 禁止使用私有或者弱加密算法

比如DES,MD5等

25. 使用ssl.SSLSocket代替socket.Socket來進行安全數據交互

26. 代碼發布前務必刪除開發者信息及包含開發者信息的注釋內容

Python代碼中的注釋不能體現的信息有:工號、姓名、部門、郵箱等。

27. 在except分支里面的raise可以不帶異常

28. 防范會話固定的最佳實踐

用戶成功登陸后,應立即使原有會話ID失效,並建立一個新的會話ID。

29. 關於跨站腳本的一些敘述

√假定所有輸入都是不可信的
×應該對所有不可信數據進行十六進制編碼,然后給字符串兩邊加等號
×JavaScrip在訪問cookie內容時,如果數據已使用\字符進行轉義,JavaScrip應該被視為可信的
√向網頁內容注入惡意標記或腳本,會竊取cookie、劫持會話或將頁面重定向到惡意網址

30. 常用來維持對象狀態一致性的手段

  • 優化代碼邏輯,避免修改對象的狀態
  • 調整邏輯順序,使可能發生異常的代碼在對象被修改前執行
  • 當業務操作失敗時,進行回滾
  • 對一個臨時的副本對象進行所需的操作,直到成功完成這些操作后,才把更新提交到原始的對象
  • 對參數進行校驗,提前避免異常

31. 避免SQL注入的推薦做法

使用預處理語句或者參數化查詢創建動態查詢

32. 最安全的序列化格式:JSON

33. pdb基本用法

使用pdb進行調試:

pdb 是 python 自帶的一個包,為 python 程序提供了一種交互的源代碼調試功能,主要特性包括設置斷點、單步調試、進入函數調試、查看當前代碼、查看棧片段、動態改變變量的值等。pdb 提供了一些常用的調試命令,詳情見表 

python調試:pdb基本用法(轉)

 下面結合具體的例子說明:

import pdb
a = "aaa"
pdb.set_trace()
b = "bbb"
c = "ccc"
final = a + b + c
print(final)
開始調試:直接運行腳本,會停留在 pdb.set_trace() 處,選擇 n+enter 可以執行當前的 statement。在第一次按下了 n+enter 之后可以直接按 enter 表示重復執行上一條 debug 命令。
n表示執行下一行

 退出 debug:使用 quit 或者 q 可以退出當前的 debug,但是 quit 會以一種非常粗魯的方式退出程序,其結果是直接 crash。

輸入了q之后:

33.1  pdb有2種用法:

非侵入式方法(不用額外修改源代碼,在命令行下直接運行就能調試)

python3 -m pdb filename.py

侵入式方法(需要在被調試的代碼中添加一行代碼然后再正常運行代碼)

import pdb;pdb.set_trace()

當你在命令行看到下面這個提示符時,說明已經正確打開了pdb

(Pdb)

然后就可以開始輸入pdb命令了,下面是pdb的常用命令

34. 哈希表的查找

哈希表:存放鍵值(地址)和數值的存儲結構
哈希函數:把數值映射(幫這個數值找一個地址)到地址的函數
為了能有效運用查找技術,必須解決的問題是:構造一個好的哈希函數,確定一個解決沖突的方法

    • 哈希函數的構造方法:
      • 直接定址法:直接以關鍵字(本身數值)或關鍵字加上某個常量作為地址
        好處:計算簡單
        缺點:關鍵字不連續的時候會造成內存浪費()就比如說:12跟134
      • 除留余數法:關鍵字除以一個整數p所得余數作為哈希地址(p小於等於哈希表長度m,但p最好小於m的素數,這種效果最好)
      • 數字分析法:提取關鍵字中取值較均勻的數字作為哈希地址
    • 哈希沖突的解決方法
      • 開放定址法:就是這個位置用不了,那我就去找用得了的位置)
        然后找用空閑位置的方法又有:
      • 線性探測法:就是這個位置用不了,那就從后面的位置依次尋找空閑的位置)
        缺點:容易發生堆聚現象;堆聚就是存入哈希表的若干個同義詞(產生地址沖突的數據)在表中連成一片,占用了其他關鍵字的映射位置。
      • 平方探測法
      • 拉鏈法:把產生沖突的位置放在一個單鏈表里)

例子1:

 例子2:

 例子3:

30%7=2

14%7=0

40%7=5

63%7=0

22%7=1

5%7=5

34.1 二次探測再散列處理

哈希表有14個桶,h(key)=key%11,現有18,37,55,61,79,如果用二次探測再散列處理沖突,則39位於第(D)個桶內。

A 6  B 8   C 4  D 10

解析:

18,37,55,61,79  和11除余分別是:  7 4 0 6 2. 沒有沖突,分別放入對應桶中

39%11=6, 被占用,  按照+1, -1, +4, -4, +9, -9... 的規則探測

(6 +1)%11 = 7 被占用

(6 - 1)%11 = 5 沒被占用,放入5號桶

(6 +4)%11=10放入10號桶


免責聲明!

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



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