⑴ python的基本術語有哪些
Python解釋器
Python文本編輯器
Python代碼運行助手
輸入和輸出
Python基礎
數據類型和變數
字元串和編碼
使用list和tuple
條件判斷
循環
使用dict和set
函數
調用函數
定義函數
函數的參數
遞歸函數
高級特性
切片
迭代
列表生成式
生成器
迭代器
函數式編程
高階函數
map/rece
filter
sorted
返回函數
匿名函數
裝飾器
偏函數
模塊
使用模塊
安裝第三方模塊
面向對象編程
類和實例
訪問限制
繼承和多態
獲取對象信息
實例屬性和類屬性
面向對象高級編程
使用__slots__
使用@property
多重繼承
定製類
使用枚舉類
使用元類
錯誤、調試和測試
錯誤處理
調試
單元測試
文檔測試
IO編程
文件讀寫
StringIO和BytesIO
操作文件和目錄
序列化
進程和線程
多進程
多線程
ThreadLocal
進程 vs. 線程
分布式進程
正則表達式
常用內建模塊
datetime
collections
base64
struct
hashlib
hmac
itertools
contextlib
urllib
XML
HTMLParser
常用第三方模塊
Pillow
requests
chardet
psutil
virtualenv
圖形界面
網路編程
TCP/IP簡介
TCP編程
UDP編程
電子郵件
SMTP發送郵件
POP3收取郵件
訪問資料庫
使用SQLite
使用MySQL
使用SQLAlchemy
Web開發
HTTP協議簡介
HTML簡介
WSGI介面
使用Web框架
使用模板
非同步IO
協程
asyncio
async/await
aiohttp
⑵ python裡面可以定義結構體嗎
Python中沒有專門定義結構體的方法,但可以使用class標記定義類來代替結構體,
其成員可以在構造函數__init__中定義,具體方法如下。
復制代碼代碼如下:
class item:
def __init__(self):
self.name = '' # 名稱
self.size = 10 # 尺寸
self.list = [] # 列表
a = item() # 定義結構對象
a.name = 'cup'
a.size = 8
a.list.append('water')
⑶ python實現刪除重復行並計數
⑷ 為啥我的Python這么慢
Pythn是動態類型而不是靜態類型的,這意味著,在程序執行時,解釋器並不知道變數的類型。對C語言來說,編譯器在聲明變數的時候就知道其類型了;對Python來說,程序執行時只知道一個變數是某種Python對象。
對於下面的C代碼
int a = 1;
int b = 2;
int c = a + b;
編譯器始終知道a和b是整型,在執行相加運算時,流程如下:
把<int> 1賦值給a
把<int> 2賦值給b
調用binary_add<int, int>(a, b)
把結果賦值給c
實現同樣功能的Python代碼如下
a = 1
b = 2
c = a + b
解釋器只知道1和2是對象,但是並不知道這個對象的類型。所以解釋器必須檢查每個變數的PyObject_HEAD才能知道變數類型,然後執行對應的相加操作,最後要創建一個新的Python對象來保存返回值,大致流程如下:
把1賦值給a
設置a->PyObject_HEAD->typecode為整型
設置a->val = 1
把2賦值給b
設置a->PyObject_HEAD->typecode為整型
設置b->val = 2
調用binary_add<int, int>(a, b)
a->PyObject_HEAD獲取類型編碼
a是一個整型;值為a->val
b->PyObject_HEAD獲取類型編碼
b是一個整型,值為b->val
調用binary_add<int, int>(a->val, b->val)
結果為整型,存在result中
創建對象c
設c->PyObject_HEAD->typecode為整型
設置c->val為result
動態類型意味著任何操作都會涉及更多的步驟。這是Python對數值操作比C語言慢的主要原因
Python是解釋型語言
上面介紹了解釋型代碼和編譯型代碼的一個區別。智能的編譯器可以提前預見並優化重復或不需要的操作,這會帶來性能的提升。編譯器是一個大的話題,這里不會展開。
Python的對象模型會帶來低效的內存訪問
和C語言的整數對比時,我們指出了Python多了額外一層信息。現在來看看數組的情況。在Python中我們可以使用標准庫中提供的List對象;而在C語言中我們會使用基於緩沖區的數組。
最簡單的NumPy數組是圍繞C數據構建的Python對象,也就是說它有一個指向連續數據緩存區的指針。而Python的list具有指向連續的指針緩沖區的指針,這些指針每個都指向一個Python對象,結合上面的例子,這些Python對象是一個整數對象。這個結構像下面這樣
很容易看出,如果你正在執行按順序逐步完成數據的操作,numpy的內存布局比Python的內存布局更為高效,無論是存儲成本還是訪問的時間成本。
為什麼使用Python
鑒於Python天生的低效率,我們為什麼還要使用Python呢?種種理由大致可以歸結為:動態類型使得Python比C更容易使用。Python非常的靈活和寬容,這種靈活性可以有效地利用開發時間,並且在那些確實需要C和Fortran優化的場合,Python可以輕松鏈接到已編譯的庫中。這也是Python在科學社區的使用率不斷增長的原因。經提到了一些結論性的東西,下面我們用Python的一些工具來做一些驗證。
下面的實驗使用到了python, ipython, numpy,版本信息如下:
python:3.6.5
1.13.3
In [1]: import sys
In [2]: import numpy
In [3]: sys.version[:5]
Out[3]: '3.6.5'
In [4]: numpy.__version__
Out[4]: '1.13.3'
本次實驗使用機器64位的機器,如果是32位的機器話,下面提到的一些struct可能會有所不同。
整數
Python的整數使用起來非常簡單。
In [5]: x = 42
In [6]: print(x)
42
介面的簡單性掩蓋了底層的復雜。在之前的內容里有提到過Python整數的內存布局。現在我們使用Python內置的ctypes模塊來自省整數類型,前提是需要知道在C API中Python整數類型的定義。
在CPython中,變數x存儲在一個名為_longobject的struct中,源碼見Include/longintrepr.h
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
}
其中PyObject_VAR_HEAD是一個宏,在Include/object.h中定義的結構如下
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size;
} PyVarObject;
其中PyObject在Include/object.h中定義如下
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
}
其中_PyObject_HEAD_EXTRA是一個在Python版本中通常不使用的宏。
將上面的信息結合起來,可以得到下面的結構
struct _longobject {
long ob_refcnt;
PyTypeObject *ob_type;
size_t ob_size;
long ob_digit[1];
}
這裡面ob_refcnt變數是對象的引用計數,ob_type是指向包含該對象所有類型信息和方法定義的結構的指針,ob_digit保存實際的數值。
有了上面的知識,可以開始使用ctypes模塊來觀察時間的對象結構並提取上面的信息。
現在來用Python定義一個C的struct
In [7]: import ctypes
In [9]: class IntStruct(ctypes.Structure):
...: _fields_ = [
...: ("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_size", ctypes.c_ulong),
...: ("ob_digit", ctypes.c_long)
...: ]
...:
...: def __repr__(self):
...: return (
...: "IntStruct(ob_digit)={self.ob_digit}, refcount={self.ob_refcnt}"
...: ).format(self=self)
...:
現在用42來做實驗。在Python中,id方法會返回對象的內存地址:
In [10]: num = 42
In [11]: IntStruct.from_address(id(42))
Out[11]: IntStruct(ob_digit)=42, refcount=61
可以看到ob_digit指向了內存中的正確位置。但是這里只創建了一個對象,為什麼引用次數是61呢?
事實證明,這是一個性能優化,Python使用了很多小的整數,如果為每一個數字都創建一個PyObject,會消耗掉不少內存。出於這個考慮,Python將一些常用的數字做了單例實現,這樣每個數字在內存中只有一份拷貝。換句話說,如果在這個范圍內創建一個新的Python整數時,只是創建了一個對該數值對象的引用。
In [16]: x = 42
In [17]: y = 42
In [18]: id(x) == id(y)
Out[18]: True
上面的例子中,x和y都指向了同一個內存地址。在使用更大的數的時候,等式就不成立了
In [19]: x = 1234
In [20]: y = 1234
In [21]: id(x) == id(y)
Out[21]: False
Python解釋器啟動時候會創建很多的整數對象;可以看看這些對象的引用分布
%matplotlib osx
import matplotlib.pyplot as plt
import sys
plt.loglog(range(1000), [sys.getrefcount(i) for i in range(1000)])
plt.xlabel('integer value')
plt.ylabel('reference count')
Out[8]: Text(0,0.5,'reference count')
可以看到0被引用了數千次,一般情況下,引用的頻率隨著整數值的增加而減少。
再來看看ob_digit對應的值
In [8]: all(i == IntStruct.from_address(id(i)).ob_digit for i in range(256))
Out[8]: True
如果更細心一點,就可以發現,對於大於256的值,ob_digit就不能對應到正確的值了:在Objects/longobject.c中對數值有一些移位操作,這也是Python對一些大整數的處理方式。
比如
In [11]: 2 ** 100
Out[11]:
這個值顯然是超過了long類型的范圍了。
List類型
現在來看看一個更復雜的數據類型:List。同樣能在Include/listobject.h中找到List類型的struct結構:
typedef struct {
PyObject_VAR_HEAD
PyObject **ob_item;
Py_ssize_t allocated;
} PyListObject;
和之前一樣,得到有效的結構體如下:
typedef struct {
long ob_refcnt;
PyTypeObject *ob_type;
Py_ssize_t ob_size;
PyObject **ob_item;
long allocated;
} PyListObject;
其中PyObject **ob_item指向list的數據,ob_size指出list中數據的個數。
In [3]: class ListStruct(ctypes.Structure):
...: _fields_ = [("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_size", ctypes.c_ulong),
...: ("ob_item", ctypes.c_long), # PyObject** pointer cast t
...: o long
...: ("allocated", ctypes.c_ulong)]
...:
...: def __repr__(self):
...: return ("ListStruct(len={self.ob_size}, "
...: "refcount={self.ob_refcnt})").format(self=self)
試驗一下
In [8]: L = [1, 2, 3, 4]
In [9]: ListStruct.from_address(id(L))
Out[9]: ListStruct(len=4, refcount=1)
為確保得到的結果是正確的,對這個list增加幾個引用,看看會不會影響引用計數:
In [10]: tup = [L, L]
In [11]: ListStruct.from_address(id(L))
Out[11]: ListStruct(len=4, refcount=3)
使用ctypes可以創建由之前IntStruct對象組成的復合結構
In [20]: Lstruct = ListStruct.from_address(id(L))
In [21]: PtrArray = Lstruct.ob_size * ctypes.POINTER(IntStruct)
In [22]: L_values = PtrArray.from_address(Lstruct.ob_item)
看看每個元素的值
In [23]: [ptr[0] for ptr in L_values]
Out[23]:
[IntStruct(ob_digit=1, refcount=4705),
IntStruct(ob_digit=2, refcount=1102),
IntStruct(ob_digit=3, refcount=559),
IntStruct(ob_digit=4, refcount=726)]
NumPy的數組
同樣的,我們來看看numpy中的數組。其C-API定義的結構見numpy/core/include/numpy/ndarraytypes.h,這里用的numpy版本是1.13.3,不同版本的結構可能有所不同。
In [25]: np.__version__
Out[25]: '1.13.3'
現在用ctypes來創建一個numpy數組的結構吧。
In [31]: class NumpyStruct(ctypes.Structure):
...: _fields_ = [("ob_refcnt", ctypes.c_long),
...: ("ob_type", ctypes.c_void_p),
...: ("ob_data", ctypes.c_long), # char* pointer cast to long
...: ("ob_ndim", ctypes.c_int),
...: ("ob_shape", ctypes.c_voidp),
...: ("ob_strides", ctypes.c_voidp)]
...:
...: @property
...: def shape(self):
...: return tuple((self.ob_ndim * ctypes.c_int64).from_address(self.ob_shape))
...:
...: @property
...: def strides(self):
...: return tuple((self.ob_ndim * ctypes.c_int64).from_address(self.ob_strides))
...:
...: def __repr__(self):
...: return ("NumpyStruct(shape={self.shape}, "
...: "refcount={self.ob_refcnt})").format(self=self)
新建一個numpy數組試試In [32]: x = np.random.random((10, 20)) In [33]: xstruct = NumpyStruct.from_address(id(x)) In [34]: xstruct Out[34]: NumpyStruct(shape=(10, 20), refcount=1)
可以看到已經拿到了正確的shape。現在看看引用計數的情況
In [35]: L = [x, x, x]
In [36]: xstruct
Out[36]: NumpyStruct(shape=(10, 20), refcount=4)
現在可以看看裡面的數據了。
In [37]: x = np.arange(10)
In [38]: xstruct = NumpyStruct.from_address(id(x))
In [39]: size = np.prod(xstruct.shape)
In [40]: arraytype = size * ctypes.c_long
In [41]: data = arraytype.from_address(xstruct.ob_data)
In [42]: [d for d in data]
Out[42]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
上面的data變數存儲了Numpy數組中定義的連續的內存塊,可以改一下其中的值。
In [43]: x[4] = 555
In [44]: [d for d in data]
Out[44]: [0, 1, 2, 3, 555, 5, 6, 7, 8, 9]
上面的例子可以證明x和data指向了同一塊連續內存。
比較Python的list和numpy的ndarray的內部結構,明顯可以看出numpy的數據對於表示同類型的數據列表來說簡單的多。
結語
Python很慢,正如上面所說,一個重要原因是類型的間接定址,這也是Python對開發者友好的原因。同時,Python本身也提供了可用於破解Python對象的工具,通過使用這些工具可以解析CPython的一些內部行為。
上
⑸ Python小問題
出現這個問題是因為索引出現了浮點數,不是索引允許的數據類型,可以驗證一下
importnumpyasnp
y=np.zeros(shape=(1,5))
arr=[nforninnp.linspace(1,5,5)]
arr里存儲的就是源代碼中會用的索引,下圖是結果
importnumpyasnp
y=np.zeros(shape=(1,5))
forninnp.int16(np.linspace(1,5,5)):
y[0,n-1]=n**2
print(y)
⑹ python3 利用struct.pack 動態組建位元組流
a = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
fmt = str(len(a)) + 'H' # 默認小端模式
struct.pack(fmt, *a) # 列表a前面加*,表示將a解壓後單個傳入參數
推理:a如果是動態變化的list,或者動態截取a其中一段來轉換成位元組流都是可以的
⑺ python用單鏈表寫一個通訊錄,包括添加,刪除(可恢復),查找等基本功能
///////////list3.c實現鏈表的插入刪除查找
#include
#include
#include
typedef
struct
LNode
//////////定義數據結構體
{
int
num;
char
name[20];
struct
LNode*
next;
}*Link;
///////////定義一個指針類型
typedef
struct
{
Link
head,tail;
int
len;
}LinkList;
LinkList
*gList;
void
MenuInfo();
void
InputData(LinkList
*mList);
void
OutputData(LinkList
*mList);
void
InsertData(LinkList
*mList,int
n);
Link
SearchNode(LinkList
*mList,int
n);
void
DeleteData(LinkList
*mList,int
n);
void
main()
{
int
_choice;
int
_quit=0;
int
n=0;
gList=(LinkList
*)malloc(sizeof(LinkList));
gList->head=gList->tail=NULL;
do
{
MenuInfo();
scanf("%d",&_choice);
switch(_choice)
⑻ python中list 合並為dataframe問題
python中要把字元串轉換成日期格式需要使用time模塊中的strptime函數,例子如下: import timet = time.strptime('2016-05-09 21:09:30', '%Y-%m-%d %H:%M:%S')print(t)執行結果如下: time.struct_time(tm_year=2016, tm_mon=5, tm_mday=9,
⑼ python二叉樹演算法
定義一顆二叉樹,請看官自行想像其形狀
class BinNode( ):
def __init__( self, val ):
self.lchild = None
self.rchild = None
self.value = val
binNode1 = BinNode( 1 )
binNode2 = BinNode( 2 )
binNode3 = BinNode( 3 )
binNode4 = BinNode( 4 )
binNode5 = BinNode( 5 )
binNode6 = BinNode( 6 )
binNode1.lchild = binNode2
binNode1.rchild = binNode3
binNode2.lchild = binNode4
binNode2.rchild = binNode5
binNode3.lchild = binNode6