全網目前最全python例子(附源碼)

源碼

github.com/javanan/pyt…html

告別枯燥,60秒學會一個小例子,系統學習Python,從入門到大師。Python之路已有190個例子:前端

第零章:感覺Python之美java

第一章:Python基礎node

第二章:Python之坑python

第三章:Python字符串和正則linux

第四章:Python文件git

第五章:Python日期程序員

第六章:Python利器github

第七章:Python畫圖正則表達式

第八章:Python實戰

第九章:Python基礎算法

第十章:Python機器學習

後續章節:

  1. 不斷豐富原有1~7章節;
  2. Python基礎算法;
  3. python 機器學習,包括機器學習的基礎概念和十大核心算法以及Sklearn和Kaggle實戰的小例子。
  4. PyQt製做GUI
  5. Flask前端開發
  6. Python數據分析:NumPy, Pandas, Matplotlib, Plotly等

已發《Python之路.1.1.pdf》最新版本包括7個章節:Python基礎Python字符串和正則Python文件Python日期, Python利器Python畫圖 章節,共計147個小例子。

感覺Python之美

1 簡潔之美

經過一行代碼,體會Python語言簡潔之美

  1. 一行代碼交換a,b
a, b = b, a
複製代碼
  1. 一行代碼反轉列表
[1,2,3][::-1] # [3,2,1]
複製代碼
  1. 一行代碼合併兩個字典
{**{'a':1,'b':2}, **{'c':3}} # {'a': 1, 'b': 2, 'c': 3}

複製代碼
  1. 一行代碼列表去重
set([1,2,2,3,3,3]) # {1, 2, 3}
複製代碼
  1. 一行代碼求多個列表中的最大值
max(max([ [1,2,3], [5,1], [4] ], key=lambda v: max(v))) # 5
複製代碼
  1. 一行代碼生成逆序序列
list(range(10,-1,-1)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
複製代碼

2 Python繪圖

Python繪圖方便、漂亮,畫圖神器pyecharts幾行代碼就能繪製出熱力圖:

image.png

炫酷的水球圖:

image.png

常用的詞雲圖:

image.png

3 Python動畫

僅適用Python的經常使用繪圖庫:Matplotlib,就能製做出動畫,輔助算法新手入門基本的排序算法。以下爲一個隨機序列,使用快速排序算法,由小到大排序的過程動畫展現:

image.png

歸併排序動畫展現:

image.png

使用turtule繪製的漫天雪花:

image.png

4 Python數據分析

Python很是適合作數值計算、數據分析,一行代碼完成數據透視:

pd.pivot_table(df, index=['Manager', 'Rep'], values=['Price'], aggfunc=np.sum)
複製代碼

5 Python機器學習

Python機器學習庫Sklearn功能強大,接口易用,包括數據預處理模塊、迴歸、分類、聚類、降維等。一行代碼建立一個KMeans聚類模型:

from sklearn.cluster import KMeans
KMeans( n_clusters=3 )
複製代碼

image.png

6 Python-GUI

PyQt設計器開發GUI,可以迅速經過拖動組建搭建出來,使用方便。以下爲使用PyQt,定製的一個專屬本身的小而美的計算器。

除此以外,使用Python的Flask框架搭建Web框架,也很是方便。

總之,在這個Python小例子,你都能學到關於使用Python幹活的方方面面的有趣的小例子,歡迎關注。

1、Python基礎

Python基礎主要總結Python經常使用內置函數;Python獨有的語法特性、關鍵詞nonlocal, global等;內置數據結構包括:列表(list), 字典(dict), 集合(set), 元組(tuple) 以及相關的高級模塊collections中的Counter, namedtuple, defaultdictheapq模塊。目前共有82個小例子

此章節一共包括82個基礎小例子。

1 求絕對值

絕對值或複數的模

In [1]: abs(-6)
Out[1]: 6
複製代碼

2 元素都爲真

接受一個迭代器,若是迭代器的全部元素都爲真,那麼返回True,不然返回False

In [2]: all([1,0,3,6])
Out[2]: False

In [3]: all([1,2,3])
Out[3]: True
複製代碼

3 元素至少一個爲真 

接受一個迭代器,若是迭代器裏至少有一個元素爲真,那麼返回True,不然返回False

In [4]: any([0,0,0,[]])
Out[4]: False

In [5]: any([0,0,1])
Out[5]: True
複製代碼

4 ascii展現對象  

調用對象的__repr__() 方法,得到該方法的返回值,以下例子返回值爲字符串

In [1]: class Student():
   ...:     def __init__(self,id,name):
   ...:         self.id = id
   ...:         self.name = name
   ...:     def __repr__(self):
   ...:         return 'id = '+self.id +', name = '+self.name
   ...: 
   ...: 

In [2]: xiaoming = Student(id='001',name='xiaoming')

In [3]: print(xiaoming)
id = 001, name = xiaoming

In [4]: ascii(xiaoming)
Out[4]: 'id = 001, name = xiaoming'
複製代碼

5 十轉二

十進制轉換爲二進制

In [1]: bin(10)
Out[1]: '0b1010'
複製代碼

6 十轉八

十進制轉換爲八進制

In [1]: oct(9)
Out[1]: '0o11'
複製代碼

7 十轉十六

十進制轉換爲十六進制

In [1]: hex(15)
Out[1]: '0xf'
複製代碼

8 判斷是真是假  

測試一個對象是True, 仍是False.

In [1]: bool([0,0,0])
Out[1]: True

In [2]: bool([])
Out[2]: False

In [3]: bool([1,0,1])
Out[3]: True
複製代碼

9 字符串轉字節  

將一個字符串轉換成字節類型

In [1]: s = "apple"

In [2]: bytes(s,encoding='utf-8')
Out[2]: b'apple'
複製代碼

10 轉爲字符串  

字符類型數值類型等轉換爲字符串類型

In [1]: i = 100

In [2]: str(i)
Out[2]: '100'
複製代碼

11 是否可調用  

判斷對象是否可被調用,能被調用的對象就是一個callable 對象,好比函數 str, int 等都是可被調用的,可是例子4xiaoming實例是不可被調用的:

In [1]: callable(str)
Out[1]: True

In [2]: callable(int)
Out[2]: True

In [3]: xiaoming
Out[3]: id = 001, name = xiaoming

In [4]: callable(xiaoming)
Out[4]: False
複製代碼

若是想讓xiaoming能被調用 xiaoming(), 須要重寫Student類的__call__方法:

In [1]: class Student():
    ...:     def __init__(self,id,name):
    ...:         self.id = id
    ...:         self.name = name
    ...:     def __repr__(self):
    ...:         return 'id = '+self.id +', name = '+self.name
    ...:     def __call__(self):
    ...:         print('I can be called')
    ...:         print(f'my name is {self.name}')
    ...: 
    ...: 

In [2]: t = Student('001','xiaoming')

In [3]: t()
I can be called
my name is xiaoming

複製代碼

12 十轉ASCII

查看十進制整數對應的ASCII字符

In [1]: chr(65)
Out[1]: 'A'
複製代碼

13 ASCII轉十

查看某個ASCII字符對應的十進制數

In [1]: ord('A')
Out[1]: 65
複製代碼

14 靜態方法 

classmethod 裝飾器對應的函數不須要實例化,不須要 self參數,但第一個參數須要是表示自身類的 cls 參數,能夠來調用類的屬性,類的方法,實例化對象等。

In [1]: class Student():
    ...:     def __init__(self,id,name):
    ...:         self.id = id
    ...:         self.name = name
    ...:     def __repr__(self):
    ...:         return 'id = '+self.id +', name = '+self.name
    ...:     @classmethod
    ...:     def f(cls):
    ...:         print(cls)
複製代碼

15 執行字符串表示的代碼

將字符串編譯成python能識別或可執行的代碼,也能夠將文字讀成字符串再編譯。

In [1]: s  = "print('helloworld')"
    
In [2]: r = compile(s,"<string>", "exec")
    
In [3]: r
Out[3]: <code object <module> at 0x0000000005DE75D0, file "<string>", line 1>
    
In [4]: exec(r)
helloworld
複製代碼

16 建立複數

建立一個複數

In [1]: complex(1,2)
Out[1]: (1+2j)
複製代碼

17 動態刪除屬性  

刪除對象的屬性

In [1]: delattr(xiaoming,'id')

In [2]: hasattr(xiaoming,'id')
Out[2]: False
複製代碼

18 轉爲字典  

建立數據字典

In [1]: dict()
Out[1]: {}

In [2]: dict(a='a',b='b')
Out[2]: {'a': 'a', 'b': 'b'}

In [3]: dict(zip(['a','b'],[1,2]))
Out[3]: {'a': 1, 'b': 2}

In [4]: dict([('a',1),('b',2)])
Out[4]: {'a': 1, 'b': 2}
複製代碼

19 一鍵查看對象全部方法 

不帶參數時返回當前範圍內的變量、方法和定義的類型列表;帶參數時返回參數的屬性,方法列表。

In [96]: dir(xiaoming)
Out[96]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 
 'name']
複製代碼

20 取商和餘數  

分別取商和餘數

In [1]: divmod(10,3)
Out[1]: (3, 1)
複製代碼

21 枚舉對象  

返回一個能夠枚舉的對象,該對象的next()方法將返回一個元組。

In [1]: s = ["a","b","c"]
    ...: for i ,v in enumerate(s,1):
    ...:     print(i,v)
    ...:
1 a
2 b
3 c
複製代碼

22 計算表達式

將字符串str 當成有效的表達式來求值並返回計算結果取出字符串中內容

In [1]: s = "1 + 3 +5"
    ...: eval(s)
    ...:
Out[1]: 9
複製代碼

23 查看變量所佔字節數

In [1]: import sys

In [2]: a = {'a':1,'b':2.0}

In [3]: sys.getsizeof(a) # 佔用240個字節
Out[3]: 240
複製代碼

24 過濾器  

在函數中設定過濾條件,迭代元素,保留返回值爲True的元素:

In [1]: fil = filter(lambda x: x>10,[1,11,2,45,7,6,13])

In [2]: list(fil)
Out[2]: [11, 45, 13]
複製代碼

25 轉爲浮點類型 

將一個整數或數值型字符串轉換爲浮點數

In [1]: float(3)
Out[1]: 3.0
複製代碼

若是不能轉化爲浮點數,則會報ValueError:

In [2]: float('a')
ValueError                                Traceback (most recent call last)
<ipython-input-11-99859da4e72c> in <module>()
----> 1 float('a')

ValueError: could not convert string to float: 'a'

複製代碼

26 字符串格式化 

格式化輸出字符串,format(value, format_spec)實質上是調用了value的__format__(format_spec)方法。

In [104]: print("i am {0},age{1}".format("tom",18))
i am tom,age18
複製代碼
3.1415926 {:.2f} 3.14 保留小數點後兩位
3.1415926 {:+.2f} +3.14 帶符號保留小數點後兩位
-1 {:+.2f} -1.00 帶符號保留小數點後兩位
2.71828 {:.0f} 3 不帶小數
5 {:0>2d} 05 數字補零 (填充左邊, 寬度爲2)
5 {:x<4d} 5xxx 數字補x (填充右邊, 寬度爲4)
10 {:x<4d} 10xx 數字補x (填充右邊, 寬度爲4)
1000000 {:,} 1,000,000 以逗號分隔的數字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00e+09 指數記法
18 {:>10d} ' 18' 右對齊 (默認, 寬度爲10)
18 {:<10d} '18 ' 左對齊 (寬度爲10)
18 {:^10d} ' 18 ' 中間對齊 (寬度爲10)

27 凍結集合  

建立一個不可修改的集合。

In [1]: frozenset([1,1,3,2,3])
Out[1]: frozenset({1, 2, 3})
複製代碼

由於不可修改,因此沒有像set那樣的addpop方法

28 動態獲取對象屬性 

獲取對象的屬性

In [1]: class Student():
   ...:     def __init__(self,id,name):
   ...:         self.id = id
   ...:         self.name = name
   ...:     def __repr__(self):
   ...:         return 'id = '+self.id +', name = '+self.name

In [2]: xiaoming = Student(id='001',name='xiaoming')
In [3]: getattr(xiaoming,'name') # 獲取xiaoming這個實例的name屬性值
Out[3]: 'xiaoming'
複製代碼

29 對象是否有這個屬性

In [1]: class Student():
   ...:     def __init__(self,id,name):
   ...:         self.id = id
   ...:         self.name = name
   ...:     def __repr__(self):
   ...:         return 'id = '+self.id +', name = '+self.name

In [2]: xiaoming = Student(id='001',name='xiaoming')
In [3]: hasattr(xiaoming,'name')
Out[3]: True

In [4]: hasattr(xiaoming,'address')
Out[4]: False
複製代碼

30 返回對象的哈希值  

返回對象的哈希值,值得注意的是自定義的實例都是可哈希的,list, dict, set等可變對象都是不可哈希的(unhashable)

In [1]: hash(xiaoming)
Out[1]: 6139638

In [2]: hash([1,2,3])
TypeError                                 Traceback (most recent call last)
<ipython-input-32-fb5b1b1d9906> in <module>()
----> 1 hash([1,2,3])

TypeError: unhashable type: 'list'
複製代碼

31 一鍵幫助 

返回對象的幫助文檔

In [1]: help(xiaoming)
Help on Student in module __main__ object:

class Student(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self, id, name)
 |
 |  __repr__(self)
 |
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)
複製代碼

32 對象門牌號 

返回對象的內存地址

In [1]: id(xiaoming)
Out[1]: 98234208
複製代碼

33 獲取用戶輸入 

獲取用戶輸入內容

In [1]: input()
aa
Out[1]: 'aa'
複製代碼

34 轉爲整型  

int(x, base =10) , x可能爲字符串或數值,將x 轉換爲一個普通整數。若是參數是字符串,那麼它可能包含符號和小數點。若是超出了普通整數的表示範圍,一個長整數被返回。

In [1]: int('12',16)
Out[1]: 18
複製代碼

35 isinstance

判斷object是否爲類classinfo的實例,是返回true

In [1]: class Student():
   ...:     def __init__(self,id,name):
   ...:         self.id = id
   ...:         self.name = name
   ...:     def __repr__(self):
   ...:         return 'id = '+self.id +', name = '+self.name

In [2]: xiaoming = Student(id='001',name='xiaoming')

In [3]: isinstance(xiaoming,Student)
Out[3]: True
複製代碼

36 父子關係鑑定

In [1]: class undergraduate(Student):
    ...:     def studyClass(self):
    ...:         pass
    ...:     def attendActivity(self):
    ...:         pass

In [2]: issubclass(undergraduate,Student)
Out[2]: True

In [3]: issubclass(object,Student)
Out[3]: False

In [4]: issubclass(Student,object)
Out[4]: True
複製代碼

若是class是classinfo元組中某個元素的子類,也會返回True

In [1]: issubclass(int,(int,float))
Out[1]: True
複製代碼

37 建立迭代器類型

使用iter(obj, sentinel), 返回一個可迭代對象, sentinel可省略(一旦迭代到此元素,當即終止)

In [1]: lst = [1,3,5]

In [2]: for i in iter(lst):
    ...:     print(i)
    ...:
1
3
5
複製代碼
In [1]: class TestIter(object):
    ...:     def __init__(self):
    ...:         self.l=[1,3,2,3,4,5]
    ...:         self.i=iter(self.l)
    ...:     def __call__(self):  #定義了__call__方法的類的實例是可調用的
    ...:         item = next(self.i)
    ...:         print ("__call__ is called,fowhich would return",item)
    ...:         return item
    ...:     def __iter__(self): #支持迭代協議(即定義有__iter__()函數)
    ...:         print ("__iter__ is called!!")
    ...:         return iter(self.l)
In [2]: t = TestIter()
In [3]: t() # 由於實現了__call__,因此t實例能被調用
__call__ is called,which would return 1
Out[3]: 1

In [4]: for e in TestIter(): # 由於實現了__iter__方法,因此t能被迭代
    ...:     print(e)
    ...: 
__iter__ is called!!
1
3
2
3
4
5
複製代碼

44 全部對象之根

object 是全部類的基類

In [1]: o = object()

In [2]: type(o)
Out[2]: object
複製代碼

45 打開文件

返回文件對象

In [1]: fo = open('D:/a.txt',mode='r', encoding='utf-8')

In [2]: fo.read()
Out[2]: '\ufefflife is not so long,\nI use Python to play.'
複製代碼

mode取值表:

字符 意義
'r' 讀取(默認)
'w' 寫入,並先截斷文件
'x' 排它性建立,若是文件已存在則失敗
'a' 寫入,若是文件存在則在末尾追加
'b' 二進制模式
't' 文本模式(默認)
'+' 打開用於更新(讀取與寫入)

46 次冪

base爲底的exp次冪,若是mod給出,取餘

In [1]: pow(3, 2, 4)
Out[1]: 1
複製代碼

47 打印

In [5]: lst = [1,3,5]

In [6]: print(lst)
[1, 3, 5]

In [7]: print(f'lst: {lst}')
lst: [1, 3, 5]

In [8]: print('lst:{}'.format(lst))
lst:[1, 3, 5]

In [9]: print('lst:',lst)
lst: [1, 3, 5]
複製代碼

48 建立屬性的兩種方式

返回 property 屬性,典型的用法:

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x
    # 使用property類建立 property 屬性
    x = property(getx, setx, delx, "I'm the 'x' property.")
複製代碼

使用python裝飾器,實現與上徹底同樣的效果代碼:

class C:
    def __init__(self):
        self._x = None

 @property
    def x(self):
        return self._x

 @x.setter
    def x(self, value):
        self._x = value

 @x.deleter
    def x(self):
        del self._x
複製代碼

49 建立range序列

  1. range(stop)
  2. range(start, stop[,step])

生成一個不可變序列:

In [1]: range(11)
Out[1]: range(0, 11)

In [2]: range(0,11,1)
Out[2]: range(0, 11)
複製代碼

50 反向迭代器

In [1]: rev = reversed([1,4,2,3,1])

In [2]: for i in rev:
     ...:     print(i)
     ...:
1
3
2
4
1
複製代碼

51 四捨五入

四捨五入,ndigits表明小數點後保留幾位:

In [11]: round(10.0222222, 3)
Out[11]: 10.022

In [12]: round(10.05,1)
Out[12]: 10.1
複製代碼

52 轉爲集合類型

返回一個set對象,集合內不容許有重複元素:

In [159]: a = [1,4,2,3,1]

In [160]: set(a)
Out[160]: {1, 2, 3, 4}
複製代碼

53 轉爲切片對象

class slice(start, stop[, step])

返回一個表示由 range(start, stop, step) 所指定索引集的 slice對象,它讓代碼可讀性、可維護性變好。

In [1]: a = [1,4,2,3,1]

In [2]: my_slice_meaning = slice(0,5,2)

In [3]: a[my_slice_meaning]
Out[3]: [1, 2, 1]
複製代碼

54 拿來就用的排序函數

排序:

In [1]: a = [1,4,2,3,1]

In [2]: sorted(a,reverse=True)
Out[2]: [4, 3, 2, 1, 1]

In [3]: a = [{'name':'xiaoming','age':18,'gender':'male'},{'name':'
     ...: xiaohong','age':20,'gender':'female'}]
In [4]: sorted(a,key=lambda x: x['age'],reverse=False)
Out[4]:
[{'name': 'xiaoming', 'age': 18, 'gender': 'male'},
 {'name': 'xiaohong', 'age': 20, 'gender': 'female'}]
複製代碼

55 求和函數

求和:

In [181]: a = [1,4,2,3,1]

In [182]: sum(a)
Out[182]: 11

In [185]: sum(a,10) #求和的初始值爲10
Out[185]: 21
複製代碼

56 轉元組

tuple() 將對象轉爲一個不可變的序列類型

In [16]: i_am_list = [1,3,5]
In [17]: i_am_tuple = tuple(i_am_list)
In [18]: i_am_tuple
Out[18]: (1, 3, 5)
複製代碼

57 查看對象類型

class type(name, bases, dict)

傳入一個參數時,返回 object 的類型:

In [1]: class Student():
   ...:     def __init__(self,id,name):
   ...:         self.id = id
   ...:         self.name = name
   ...:     def __repr__(self):
   ...:         return 'id = '+self.id +', name = '+self.name
   ...: 
   ...: 

In [2]: xiaoming = Student(id='001',name='xiaoming')
In [3]: type(xiaoming)
Out[3]: __main__.Student

In [4]: type(tuple())
Out[4]: tuple
複製代碼

58 聚合迭代器

建立一個聚合了來自每一個可迭代對象中的元素的迭代器:

In [1]: x = [3,2,1]
In [2]: y = [4,5,6]
In [3]: list(zip(y,x))
Out[3]: [(4, 3), (5, 2), (6, 1)]

In [4]: a = range(5)
In [5]: b = list('abcde')
In [6]: b
Out[6]: ['a', 'b', 'c', 'd', 'e']
In [7]: [str(y) + str(x) for x,y in zip(a,b)]
Out[7]: ['a0', 'b1', 'c2', 'd3', 'e4']
複製代碼

59 nonlocal用於內嵌函數中

關鍵詞nonlocal經常使用於函數嵌套中,聲明變量i爲非局部變量; 若是不聲明,i+=1代表i爲函數wrapper內的局部變量,由於在i+=1引用(reference)時,i未被聲明,因此會報unreferenced variable的錯誤。

def excepter(f):
    i = 0
    t1 = time.time()
    def wrapper(): 
        try:
            f()
        except Exception as e:
            nonlocal i
            i += 1
            print(f'{e.args[0]}: {i}')
            t2 = time.time()
            if i == n:
                print(f'spending time:{round(t2-t1,2)}')
    return wrapper
複製代碼

60 global 聲明全局變量

先回答爲何要有global,一個變量被多個函數引用,想讓全局變量被全部函數共享。有的夥伴可能會想這還不簡單,這樣寫:

i = 5
def f():
    print(i)

def g():
    print(i)
    pass

f()
g()

複製代碼

f和g兩個函數都能共享變量i,程序沒有報錯,因此他們依然不明白爲何要用global.

可是,若是我想要有個函數對i遞增,這樣:

def h():
    i += 1

h()
複製代碼

此時執行程序,bang, 出錯了! 拋出異常:UnboundLocalError,原來編譯器在解釋i+=1時會把i解析爲函數h()內的局部變量,很顯然在此函數內,編譯器找不到對變量i的定義,因此會報錯。

global就是爲解決此問題而被提出,在函數h內,顯示地告訴編譯器i爲全局變量,而後編譯器會在函數外面尋找i的定義,執行完i+=1後,i還爲全局變量,值加1:

i = 0
def h():
    global i
    i += 1

h()
print(i)
複製代碼

61 鏈式比較

i = 3
print(1 < i < 3)  # False
print(1 < i <= 3)  # True
複製代碼

62 不用else和if實現計算器

from operator import *


def calculator(a, b, k):
    return {
        '+': add,
        '-': sub,
        '*': mul,
        '/': truediv,
        '**': pow
    }[k](a, b)


calculator(1, 2, '+')  # 3
calculator(3, 4, '**')  # 81
複製代碼

63 鏈式操做

from operator import (add, sub)


def add_or_sub(a, b, oper):
    return (add if oper == '+' else sub)(a, b)


add_or_sub(1, 2, '-')  # -1
複製代碼

64 交換兩元素

def swap(a, b):
    return b, a


print(swap(1, 0))  # (0,1)
複製代碼

65 去最求平均

def score_mean(lst):
    lst.sort()
    lst2=lst[1:(len(lst)-1)]
    return round((sum(lst2)/len(lst2)),1)

lst=[9.1, 9.0,8.1, 9.7, 19,8.2, 8.6,9.8]
score_mean(lst) # 9.1
複製代碼

66 打印99乘法表

打印出以下格式的乘法表

1*1=1
1*2=2   2*2=4
1*3=3   2*3=6   3*3=9
1*4=4   2*4=8   3*4=12  4*4=16
1*5=5   2*5=10  3*5=15  4*5=20  5*5=25
1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81
複製代碼

一共有10 行,第i行的第j列等於:j*i

其中,

i取值範圍:1<=i<=9

j取值範圍:1<=j<=i

根據例子分析的語言描述,轉化爲以下代碼:

for i in range(1,10):
    ...:     for j in range(1,i+1):
    ...:         print('%d*%d=%d'%(j,i,j*i),end="\t")
    ...:     print()
複製代碼

67 全展開

對於以下數組:

[[[1,2,3],[4,5]]]
複製代碼

如何徹底展開成一維的。這個小例子實現的flatten是遞歸版,兩個參數分別表示帶展開的數組,輸出數組。

from collections.abc import *

def flatten(lst, out_lst=None):
    if out_lst is None:
        out_lst = []
    for i in lst:
        if isinstance(i, Iterable): # 判斷i是否可迭代
            flatten(i, out_lst)  # 尾數遞歸
        else:
            out_lst.append(i)    # 產生結果
    return out_lst
複製代碼

調用flatten:

print(flatten([[1,2,3],[4,5]]))
print(flatten([[1,2,3],[4,5]], [6,7]))
print(flatten([[[1,2,3],[4,5,6]]]))
# 結果:
[1, 2, 3, 4, 5]
[6, 7, 1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
複製代碼

numpy裏的flatten與上面的函數實現有些微妙的不一樣:

import numpy
b = numpy.array([[1,2,3],[4,5]])
b.flatten()
array([list([1, 2, 3]), list([4, 5])], dtype=object)
複製代碼

68 列表等分

from math import ceil

def divide(lst, size):
    if size <= 0:
        return [lst]
    return [lst[i * size:(i+1)*size] for i in range(0, ceil(len(lst) / size))]


r = divide([1, 3, 5, 7, 9], 2)
print(r)  # [[1, 3], [5, 7], [9]]

r = divide([1, 3, 5, 7, 9], 0)
print(r)  # [[1, 3, 5, 7, 9]]

r = divide([1, 3, 5, 7, 9], -3)
print(r)  # [[1, 3, 5, 7, 9]]

複製代碼

69 列表壓縮

def filter_false(lst):
    return list(filter(bool, lst))


r = filter_false([None, 0, False, '', [], 'ok', [1, 2]])
print(r)  # ['ok', [1, 2]]

複製代碼

70 更長列表

def max_length(*lst):
    return max(*lst, key=lambda v: len(v))


r = max_length([1, 2, 3], [4, 5, 6, 7], [8])
print(f'更長的列表是{r}')  # [4, 5, 6, 7]

r = max_length([1, 2, 3], [4, 5, 6, 7], [8, 9])
print(f'更長的列表是{r}')  # [4, 5, 6, 7]
複製代碼

71 求衆數

def top1(lst):
    return max(lst, default='列表爲空', key=lambda v: lst.count(v))

lst = [1, 3, 3, 2, 1, 1, 2]
r = top1(lst)
print(f'{lst}中出現次數最多的元素爲:{r}')  # [1, 3, 3, 2, 1, 1, 2]中出現次數最多的元素爲:1
複製代碼

72 多表之最

def max_lists(*lst):
    return max(max(*lst, key=lambda v: max(v)))


r = max_lists([1, 2, 3], [6, 7, 8], [4, 5])
print(r)  # 8
複製代碼

73 列表查重

def has_duplicates(lst):
    return len(lst) == len(set(lst))


x = [1, 1, 2, 2, 3, 2, 3, 4, 5, 6]
y = [1, 2, 3, 4, 5]
has_duplicates(x)  # False
has_duplicates(y)  # True
複製代碼

74 列表反轉

def reverse(lst):
    return lst[::-1]


r = reverse([1, -2, 3, 4, 1, 2])
print(r)  # [2, 1, 4, 3, -2, 1]
複製代碼

75 浮點數等差數列

def rang(start, stop, n):
    start,stop,n = float('%.2f' % start), float('%.2f' % stop),int('%.d' % n)
    step = (stop-start)/n
    lst = [start]
    while n > 0:
        start,n = start+step,n-1
        lst.append(round((start), 2))
    return lst

rang(1, 8, 10) # [1.0, 1.7, 2.4, 3.1, 3.8, 4.5, 5.2, 5.9, 6.6, 7.3, 8.0]
複製代碼

76 按條件分組

def bif_by(lst, f):
    return [ [x for x in lst if f(x)],[x for x in lst if not f(x)]]

records = [25,89,31,34] 
bif_by(records, lambda x: x<80) # [[25, 31, 34], [89]]
複製代碼

77 map實現向量運算

#多序列運算函數—map(function,iterabel,iterable2)
lst1=[1,2,3,4,5,6]
lst2=[3,4,5,6,3,2]
list(map(lambda x,y:x*y+1,lst1,lst2))
### [4, 9, 16, 25, 16, 13]
複製代碼

78 值最大的字典

def max_pairs(dic):
    if len(dic) == 0:
        return dic
    max_val = max(map(lambda v: v[1], dic.items()))
    return [item for item in dic.items() if item[1] == max_val]


r = max_pairs({'a': -10, 'b': 5, 'c': 3, 'd': 5})
print(r)  # [('b', 5), ('d', 5)]
複製代碼

79 合併兩個字典

def merge_dict2(dic1, dic2):
    return {**dic1, **dic2}  # python3.5後支持的一行代碼實現合併字典

merge_dict({'a': 1, 'b': 2}, {'c': 3})  # {'a': 1, 'b': 2, 'c': 3}
複製代碼

80 topn字典

from heapq import nlargest

# 返回字典d前n個最大值對應的鍵

def topn_dict(d, n):
    return nlargest(n, d, key=lambda k: d[k])

topn_dict({'a': 10, 'b': 8, 'c': 9, 'd': 10}, 3)  # ['a', 'd', 'c']
複製代碼

81 異位詞

from collections import Counter

# 檢查兩個字符串是否 相同字母異序詞,簡稱:互爲變位詞

def anagram(str1, str2):
    return Counter(str1) == Counter(str2)

anagram('eleven+two', 'twelve+one')  # True 這是一對神器的變位詞
anagram('eleven', 'twelve')  # False
複製代碼

82 邏輯上合併字典

(1) 兩種合併字典方法 這是通常的字典合併寫法

dic1 = {'x': 1, 'y': 2 }
dic2 = {'y': 3, 'z': 4 }
merged1 = {**dic1, **dic2} # {'x': 1, 'y': 3, 'z': 4}
複製代碼

修改merged['x']=10,dic1中的x值不變merged是從新生成的一個新字典

可是,ChainMap卻不一樣,它在內部建立了一個容納這些字典的列表。所以使用ChainMap合併字典,修改merged['x']=10後,dic1中的x值改變,以下所示:

from collections import ChainMap
merged2 = ChainMap(dic1,dic2)
print(merged2) # ChainMap({'x': 1, 'y': 2}, {'y': 3, 'z': 4})
複製代碼

83 命名元組提升可讀性

from collections import namedtuple
Point = namedtuple('Point', ['x', 'y', 'z'])  # 定義名字爲Point的元祖,字段屬性有x,y,z
lst = [Point(1.5, 2, 3.0), Point(-0.3, -1.0, 2.1), Point(1.3, 2.8, -2.5)]
print(lst[0].y - lst[1].y)
複製代碼

使用命名元組寫出來的代碼可讀性更好,尤爲處理上百上千個屬性時做用更加凸顯。

84 樣本抽樣

使用sample抽樣,以下例子從100個樣本中隨機抽樣10個。

from random import randint,sample
lst = [randint(0,50) for _ in range(100)]
print(lst[:5])# [38, 19, 11, 3, 6]
lst_sample = sample(lst,10)
print(lst_sample) # [33, 40, 35, 49, 24, 15, 48, 29, 37, 24]
複製代碼

85 重洗數據集

使用shuffle用來重洗數據集,值得注意shuffle是對lst就地(in place)洗牌,節省存儲空間

from random import shuffle
lst = [randint(0,50) for _ in range(100)]
shuffle(lst)
print(lst[:5]) # [50, 3, 48, 1, 26]
複製代碼

86 10個均勻分佈的座標點

random模塊中的uniform(a,b)生成[a,b)內的一個隨機數,以下生成10個均勻分佈的二維座標點

from random import uniform
In [1]: [(uniform(0,10),uniform(0,10)) for _ in range(10)]
Out[1]: 
[(9.244361194237328, 7.684326645514235),
 (8.129267671737324, 9.988395854203773),
 (9.505278771040661, 2.8650440524834107),
 (3.84320100484284, 1.7687190176304601),
 (6.095385729409376, 2.377133802224657),
 (8.522913365698605, 3.2395995841267844),
 (8.827829601859406, 3.9298809217233766),
 (1.4749644859469302, 8.038753079253127),
 (9.005430657826324, 7.58011186920019),
 (8.700789540392917, 1.2217577293254112)]
複製代碼

87 10個高斯分佈的座標點

random模塊中的gauss(u,sigma)生成均值爲u, 標準差爲sigma的知足高斯分佈的值,以下生成10個二維座標點,樣本偏差(y-2*x-1)知足均值爲0,標準差爲1的高斯分佈:

from random import gauss
x = range(10)
y = [2*xi+1+gauss(0,1) for xi in x]
points = list(zip(x,y))
### 10個二維點:
[(0, -0.86789025305992),
 (1, 4.738439437453464),
 (2, 5.190278040856102),
 (3, 8.05270893133576),
 (4, 9.979481700775292),
 (5, 11.960781766216384),
 (6, 13.025427054303737),
 (7, 14.02384035204836),
 (8, 15.33755823101161),
 (9, 17.565074449028497)]
複製代碼

88 chain高效串聯多個容器對象

chain函數串聯a和b,兼顧內存效率同時寫法更加優雅。

from itertools import chain
a = [1,3,5,0]
b = (2,4,6)

for i in chain(a,b):
  print(i)
### 結果
1
3
5
0
2
4
6
複製代碼

89 操做函數對象

In [31]: def f():
    ...:     print('i\'m f')
    ...:

In [32]: def g():
    ...:     print('i\'m g')
    ...:

In [33]: [f,g][1]()
i'm g
複製代碼

建立函數對象的list,根據想要調用的index,方便統一調用。

90 生成逆序序列

list(range(10,-1,-1)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
複製代碼

第三個參數爲負時,表示從第一個參數開始遞減,終止到第二個參數(不包括此邊界)

二 Python之坑

1 含單個元素的元組

Python中有些函數的參數類型爲元組,其內有1個元素,這樣建立是錯誤的:

c = (5) # NO!
複製代碼

它實際建立一個整型元素5,必需要在元素後加一個逗號:

c = (5,) # YES!
複製代碼

2 默認參數設爲空

含有默認參數的函數,若是類型爲容器,且設置爲空:

def f(a,b=[]):  # NO!
    print(b)
    return b

ret = f(1)
ret.append(1)
ret.append(2)
# 當再調用f(1)時,預計打印爲 []
f(1)
# 可是卻爲 [1,2]
複製代碼

這是可變類型的默認參數之坑,請務必設置此類默認參數爲None:

def f(a,b=None): # YES!
    pass
複製代碼

3 共享變量未綁定之坑

有時想要多個函數共享一個全局變量,但卻在某個函數內試圖修改它爲局部變量:

i = 1
def f():
    i+=1 #NO!
    
def g():
    print(i)
複製代碼

應該在f函數內顯示聲明i爲global變量:

i = 1
def f():
    global i # YES!
    i+=1
複製代碼

4 lambda自由參數之坑

排序和分組的key函數常使用lambda,表達更加簡潔,可是有個坑新手容易掉進去:

a = [lambda x: x+i for i in range(3)] # NO!
for f in a:
    print(f(1))
# 你可能指望輸出:1,2,3
複製代碼

可是實際卻輸出: 3,3,3. 定義lambda使用的i被稱爲自由參數,它只在調用lambda函數時,值才被真正肯定下來,這就猶以下面打印出2,你確定確信無疑吧。

a = 0
a = 1
a = 2
def f(a):
    print(a)
複製代碼

正確作法是轉化自由參數爲lambda函數的默認參數

a = [lambda x,i=i: x+i for i in range(3)] # YES!
複製代碼

5 分不清是默認參數仍是關鍵字參數

定義函數f,在使用它時,width的如下三種寫法都是OK的,若是未了解函數原型,容易分不清width究竟是位置參數仍是關鍵字參數。

def f(a,width=10.0):
    print(width)

f(1,width=15.0) # 15.0 # 容易分不清width是位置參數仍是關鍵字參數
f(1,15.0) # 15.0
f(1) # 10.0
複製代碼

width是帶默認參數的位置參數,關鍵字參數必須使用兩個星號聲明。所以若是要區分它們,須要關注函數的定義。

def f(a,**b):
    print(b)
f(1,width=15.0) # width是關鍵字參數,不是默認參數
複製代碼

6 列表刪除之坑

刪除一個列表中的元素,此元素可能在列表中重複屢次:

def del_item(lst,e):
    return [lst.remove(i) for i in e if i==e] # NO!
複製代碼

考慮刪除這個序列[1,3,3,3,5]中的元素3,結果發現只刪除其中兩個:

del_item([1,3,3,3,5],3) # 結果:[1,3,5]
複製代碼

正確作法:

def del_item(lst,e):
    d = dict(zip(range(len(lst)),lst)) # YES! 構造字典
    return [v for k,v in d.items() if v!=e]

複製代碼

7 列表快速複製之坑

在python中*與列表操做,實現快速元素複製:

a = [1,3,5] * 3 # [1,3,5,1,3,5,1,3,5]
a[0] = 10 # [10, 2, 3, 1, 2, 3, 1, 2, 3]
複製代碼

若是列表元素爲列表或字典等複合類型:

a = [[1,3,5],[2,4]] * 3 # [[1, 3, 5], [2, 4], [1, 3, 5], [2, 4], [1, 3, 5], [2, 4]]

a[0][0] = 10 # 
複製代碼

結果可能出乎你的意料,其餘a[1[0]等也被修改成10

[[10, 3, 5], [2, 4], [10, 3, 5], [2, 4], [10, 3, 5], [2, 4]]
複製代碼

這是由於*複製的複合對象都是淺引用,也就是說id(a[0])與id(a[2])門牌號是相等的。若是想要實現深複製效果,這麼作:

a = [[] for _ in range(3)]
複製代碼

8 字符串駐留

In [1]: a = 'something'
    ...: b = 'some'+'thing'
    ...: id(a)==id(b)
Out[1]: True
複製代碼

若是上面例子返回True,可是下面例子爲何是False:

In [1]: a = '@zglg.com'

In [2]: b = '@zglg'+'.com'

In [3]: id(a)==id(b)
Out[3]: False
複製代碼

這與Cpython 編譯優化相關,行爲稱爲字符串駐留,但駐留的字符串中只包含字母,數字或下劃線。

9 相同值的不可變對象

In [5]: d = {}
    ...: d[1] = 'java'
    ...: d[1.0] = 'python'

In [6]: d
Out[6]: {1: 'python'}

### key=1,value=java的鍵值對神器消失了
In [7]: d[1]
Out[7]: 'python'
In [8]: d[1.0]
Out[8]: 'python'
複製代碼

這是由於具備相同值的不可變對象在Python中始終具備相同的哈希值

因爲存在哈希衝突,不一樣值的對象也可能具備相同的哈希值。

10 對象銷燬順序

建立一個類SE:

class SE(object):
  def __init__(self):
    print('init')
  def __del__(self):
    print('del')
複製代碼

建立兩個SE實例,使用is判斷:

In [63]: SE() is SE()
init
init
del
del
Out[63]: False

複製代碼

建立兩個SE實例,使用id判斷:

In [64]: id(SE()) == id(SE())
init
del
init
del
Out[64]: True
複製代碼

調用id函數, Python 建立一個 SE 類的實例,並使用id函數得到內存地址後,銷燬內存丟棄這個對象。

當連續兩次進行此操做, Python會將相同的內存地址分配給第二個對象,因此兩個對象的id值是相同的.

可是is行爲卻與之不一樣,經過打印順序就能夠看到。

11 充分認識for

In [65]: for i in range(5):
    ...:   print(i)
    ...:   i = 10
0
1
2
3
4
複製代碼

爲何不是執行一次就退出?

按照for在Python中的工做方式, i = 10 並不會影響循環。range(5)生成的下一個元素就被解包,並賦值給目標列表的變量i.

12 認識執行時機

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)
複製代碼

g爲生成器,list(g)後返回[1,3,5],由於每一個元素確定至少都出現一次。因此這個結果這不足爲奇。可是,請看下例:

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)
array = [5, 7, 9]
複製代碼

請問,list(g)等於多少?這不是和上面那個例子結果同樣嗎,結果也是[1,3,5],可是:

In [74]: list(g)
Out[74]: [5]
複製代碼

這有些難以想象~~ 緣由在於:

生成器表達式中, in 子句在聲明時執行, 而條件子句則是在運行時執行。

因此代碼:

array = [1, 3, 5]
g = (x for x in array if array.count(x) > 0)
array = [5, 7, 9]
複製代碼

等價於:

g = (x for x in [1,3,5] if [5,7,9].count(x) > 0)
複製代碼

正在陸續彙總更多Python使用之坑 ...

3、Python字符串和正則

字符串無所不在,字符串的處理也是最多見的操做。本章節將總結和字符串處理相關的一切操做。主要包括基本的字符串操做;高級字符串操做之正則。目前共有16個小例子

1 反轉字符串

st="python"
#方法1
''.join(reversed(st))
#方法2
st[::-1]
複製代碼

2 字符串切片操做

字符串切片操做——查找替換35的倍數
In [1]:[str("java"[i%3*4:]+"python"[i%5*6:] or i) for i in range(1,15)]
OUT[1]:['1',
 '2',
 'java',
 '4',
 'python',
 'java',
 '7',
 '8',
 'java',
 'python',
 '11',
 'java',
 '13',
 '14']
複製代碼

3 join串聯字符串

In [4]: mystr = ['1',
   ...:  '2',
   ...:  'java',
   ...:  '4',
   ...:  'python',
   ...:  'java',
   ...:  '7',
   ...:  '8',
   ...:  'java',
   ...:  'python',
   ...:  '11',
   ...:  'java',
   ...:  '13',
   ...:  '14']

In [5]: ','.join(mystr) #用逗號鏈接字符串
Out[5]: '1,2,java,4,python,java,7,8,java,python,11,java,13,14'
複製代碼

4 字符串的字節長度

def str_byte_len(mystr):
    return (len(mystr.encode('utf-8')))


str_byte_len('i love python')  # 13(個字節)
str_byte_len('字符')  # 6(個字節)
複製代碼

如下是正則部分

import re
複製代碼

1 查找第一個匹配串

s = 'i love python very much'
pat = 'python' 
r = re.search(pat,s)
print(r.span()) #(7,13)
複製代碼

2 查找全部1的索引

s = '山東省濰坊市青州第1中學高三1班'
pat = '1'
r = re.finditer(pat,s)
for i in r:
    print(i)

# <re.Match object; span=(9, 10), match='1'>
# <re.Match object; span=(14, 15), match='1'>
複製代碼

3 \d 匹配數字[0-9]

findall找出所有位置的全部匹配

s = '一共20行代碼運行時間13.59s'
pat = r'\d+' # +表示匹配數字(\d表示數字的通用字符)1次或屢次
r = re.findall(pat,s)
print(r)
# ['20', '13', '59']
複製代碼

4 匹配浮點數

?表示前一個字符匹配0或1次

s = '一共20行代碼運行時間13.59s'
pat = r'\d+\.?\d+' # ?表示匹配小數點(\.)0次或1次
r = re.findall(pat,s)
print(r)
# ['20', '13.59']
複製代碼

5 ^匹配字符串的開頭

s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'^[emrt]' # 查找以字符e,m,r或t開始的字符串
r = re.findall(pat,s)
print(r)
# [],由於字符串的開頭是字符`T`,不在emrt匹配範圍內,因此返回爲空
IN [11]: s2 = 'email for me is guozhennianhua@163.com'
re.findall('^[emrt].*',s2)# 匹配以e,m,r,t開始的字符串,後面是多個任意字符
Out[11]: ['email for me is guozhennianhua@163.com']

複製代碼

6 re.I 忽略大小寫

s = 'That'
pat = r't' 
r = re.findall(pat,s,re.I)
In [22]: r
Out[22]: ['T', 't']
複製代碼

7 理解compile的做用

若是要作不少次匹配,能夠先編譯匹配串:

import re
pat = re.compile('\W+') # \W 匹配不是數字和字母的字符
has_special_chars = pat.search('ed#2@edc') 
if has_special_chars:
    print(f'str contains special characters:{has_special_chars.group(0)}')

###輸出結果: 
 # str contains special characters:# 

### 再次使用pat正則編譯對象 作匹配
again_pattern = pat.findall('guozhennianhua@163.com')
if '@' in again_pattern:
    print('possibly it is an email')

複製代碼

8 使用()捕獲單詞,不想帶空格

使用()捕獲

s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s([a-zA-Z]+)'  
r = re.findall(pat,s)
print(r) #['module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']
複製代碼

看到提取單詞中未包括第一個單詞,使用?表示前面字符出現0次或1次,可是此字符還有表示貪心或非貪心匹配含義,使用時要謹慎。

s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s?([a-zA-Z]+)'  
r = re.findall(pat,s)
print(r) #['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']
複製代碼

9 split分割單詞

使用以上方法分割單詞不是簡潔的,僅僅是爲了演示。分割單詞最簡單仍是使用split函數。

s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s+'  
r = re.split(pat,s)
print(r) # ['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']

### 上面這句話也可直接使用str自帶的split函數:
s.split(' ') #使用空格分隔

### 可是,對於風格符更加複雜的狀況,split無能爲力,只能使用正則

s = 'This,,, module ; \t provides|| regular ; '
words = re.split('[,\s;|]+',s)  #這樣分隔出來,最後會有一個空字符串
words = [i for i in words if len(i)>0]
複製代碼

10 match從字符串開始位置匹配

注意match,search等的不一樣:

  1. match函數
import re
### match
mystr = 'This'
pat = re.compile('hi')
pat.match(mystr) # None
pat.match(mystr,1) # 從位置1處開始匹配
Out[90]: <re.Match object; span=(1, 3), match='hi'>
複製代碼
  1. search函數 search是從字符串的任意位置開始匹配
In [91]: mystr = 'This'
    ...: pat = re.compile('hi')
    ...: pat.search(mystr)
Out[91]: <re.Match object; span=(1, 3), match='hi'>
複製代碼

11 替換匹配的子串

sub函數實現對匹配子串的替換

content="hello 12345, hello 456321"    
pat=re.compile(r'\d+') #要替換的部分
m=pat.sub("666",content)
print(m) # hello 666, hello 666
複製代碼

12 貪心捕獲

(.*)表示捕獲任意多個字符,儘量多的匹配字符

content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*)</div>")  #貪婪模式
m=pat.findall(content)
print(m) #匹配結果爲: ['graph</div>bb<div>math']
複製代碼

13 非貪心捕獲

僅添加一個問號(?),獲得結果徹底不一樣,這是非貪心匹配,經過這個例子體會貪心和非貪心的匹配的不一樣。

content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*?)</div>")
m=pat.findall(content)
print(m) # ['graph', 'math']
複製代碼

非貪心捕獲,見好就收。

14 經常使用元字符總結

. 匹配任意字符  
^ 匹配字符串開始位置 
$ 匹配字符串中結束的位置 
* 前面的原子重複0次、1次、屢次 
? 前面的原子重複0次或者1次 
+ 前面的原子重複1次或屢次
{n} 前面的原子出現了 n 次
{n,} 前面的原子至少出現 n 次
{n,m} 前面的原子出現次數介於 n-m 之間
( ) 分組,須要輸出的部分
複製代碼

15 經常使用通用字符總結

\s  匹配空白字符 
\w  匹配任意字母/數字/下劃線 
\W  和小寫 w 相反,匹配任意字母/數字/下劃線之外的字符
\d  匹配十進制數字
\D  匹配除了十進制數之外的值 
[0-9]  匹配一個0-9之間的數字
[a-z]  匹配小寫英文字母
[A-Z]  匹配大寫英文字母
複製代碼

14 密碼安全檢查

密碼安全要求:1)要求密碼爲6到20位; 2)密碼只包含英文字母和數字

pat = re.compile(r'\w{6,20}') # 這是錯誤的,由於\w通配符匹配的是字母,數字和下劃線,題目要求不能含有下劃線
# 使用最穩的方法:\da-zA-Z知足`密碼只包含英文字母和數字`
pat = re.compile(r'[\da-zA-Z]{6,20}')
複製代碼

選用最保險的fullmatch方法,查看是否整個字符串都匹配:

pat.fullmatch('qaz12') # 返回 None, 長度小於6
pat.fullmatch('qaz12wsxedcrfvtgb67890942234343434') # None 長度大於22
pat.fullmatch('qaz_231') # None 含有下劃線
pat.fullmatch('n0passw0Rd')
Out[4]: <re.Match object; span=(0, 10), match='n0passw0Rd'>
複製代碼

15 爬取百度首頁標題

import re
from urllib import request

#爬蟲爬取百度首頁內容
data=request.urlopen("http://www.baidu.com/").read().decode()

#分析網頁,肯定正則表達式
pat=r'<title>(.*?)</title>'

result=re.search(pat,data)
print(result) <re.Match object; span=(1358, 1382), match='<title>百度一下,你就知道</title>'>

result.group() # 百度一下,你就知道
複製代碼

16 批量轉化爲駝峯格式(Camel)

數據庫字段名批量轉化爲駝峯格式

分析過程

# 用到的正則串講解
# \s 指匹配: [ \t\n\r\f\v]
# A|B:表示匹配A串或B串
# re.sub(pattern, newchar, string): 
# substitue代替,用newchar字符替代與pattern匹配的字符全部.
複製代碼
# title(): 轉化爲大寫,例子:
# 'Hello world'.title() # 'Hello World'
複製代碼
# print(re.sub(r"\s|_|", "", "He llo_worl\td"))
s = re.sub(r"(\s|_|-)+", " ",
           'some_database_field_name').title().replace(" ", "")  
#結果: SomeDatabaseFieldName
複製代碼
# 能夠看到此時的第一個字符爲大寫,須要轉化爲小寫
s = s[0].lower()+s[1:]  # 最終結果
複製代碼

整理以上分析獲得以下代碼:

import re
def camel(s):
    s = re.sub(r"(\s|_|-)+", " ", s).title().replace(" ", "")
    return s[0].lower() + s[1:]

# 批量轉化
def batch_camel(slist):
    return [camel(s) for s in slist]
複製代碼

測試結果:

s = batch_camel(['student_id', 'student\tname', 'student-add'])
print(s)
# 結果
['studentId', 'studentName', 'studentAdd']
複製代碼

4、Python文件

1 獲取後綴名

import os
file_ext = os.path.splitext('./data/py/test.py')
front,ext = file_ext
In [5]: front
Out[5]: './data/py/test'

In [6]: ext
Out[6]: '.py'
複製代碼

2 文件讀操做

import os
# 建立文件夾

def mkdir(path):
    isexists = os.path.exists(path)
    if not isexists:
        os.mkdir(path)
# 讀取文件信息

def openfile(filename):
    f = open(filename)
    fllist = f.read()
    f.close()
    return fllist  # 返回讀取內容
複製代碼

3 文件寫操做

# 寫入文件信息
# example1
# w寫入,若是文件存在,則清空內容後寫入,不存在則建立
f = open(r"./data/test.txt", "w", encoding="utf-8")
print(f.write("測試文件寫入"))
f.close

# example2
# a寫入,文件存在,則在文件內容後追加寫入,不存在則建立
f = open(r"./data/test.txt", "a", encoding="utf-8")
print(f.write("測試文件寫入"))
f.close

# example3
# with關鍵字系統會自動關閉文件和處理異常
with open(r"./data/test.txt", "w") as f:
    f.write("hello world!")
複製代碼

4 路徑中的文件名

In [11]: import os
    ...: file_ext = os.path.split('./data/py/test.py')
    ...: ipath,ifile = file_ext
    ...:

In [12]: ipath
Out[12]: './data/py'

In [13]: ifile
Out[13]: 'test.py'
複製代碼

5 批量修改文件後綴

批量修改文件後綴

本例子使用Python的os模塊和 argparse模塊,將工做目錄work_dir下全部後綴名爲old_ext的文件修改成後綴名爲new_ext

經過本例子,你們將會大概清楚argparse模塊的主要用法。

導入模塊

import argparse
import os
複製代碼

定義腳本參數

def get_parser():
    parser = argparse.ArgumentParser(
        description='工做目錄中文件後綴名修改')
    parser.add_argument('work_dir', metavar='WORK_DIR', type=str, nargs=1,
                        help='修改後綴名的文件目錄')
    parser.add_argument('old_ext', metavar='OLD_EXT',
                        type=str, nargs=1, help='原來的後綴')
    parser.add_argument('new_ext', metavar='NEW_EXT',
                        type=str, nargs=1, help='新的後綴')
    return parser
複製代碼

後綴名批量修改

def batch_rename(work_dir, old_ext, new_ext):
    """ 傳遞當前目錄,原來後綴名,新的後綴名後,批量重命名後綴 """
    for filename in os.listdir(work_dir):
        # 獲取獲得文件後綴
        split_file = os.path.splitext(filename)
        file_ext = split_file[1]
        # 定位後綴名爲old_ext 的文件
        if old_ext == file_ext:
            # 修改後文件的完整名稱
            newfile = split_file[0] + new_ext
            # 實現重命名操做
            os.rename(
                os.path.join(work_dir, filename),
                os.path.join(work_dir, newfile)
            )
    print("完成重命名")
    print(os.listdir(work_dir))
複製代碼

實現Main

def main():
    """ main函數 """
    # 命令行參數
    parser = get_parser()
    args = vars(parser.parse_args())
    # 從命令行參數中依次解析出參數
    work_dir = args['work_dir'][0]
    old_ext = args['old_ext'][0]
    if old_ext[0] != '.':
        old_ext = '.' + old_ext
    new_ext = args['new_ext'][0]
    if new_ext[0] != '.':
        new_ext = '.' + new_ext

    batch_rename(work_dir, old_ext, new_ext)
複製代碼

6 xls批量轉換成xlsx

import os


def xls_to_xlsx(work_dir):
    """ 傳遞當前目錄,原來後綴名,新的後綴名後,批量重命名後綴 """
    old_ext, new_ext = '.xls', '.xlsx'
    for filename in os.listdir(work_dir):
        # 獲取獲得文件後綴
        split_file = os.path.splitext(filename)
        file_ext = split_file[1]
        # 定位後綴名爲old_ext 的文件
        if old_ext == file_ext:
            # 修改後文件的完整名稱
            newfile = split_file[0] + new_ext
            # 實現重命名操做
            os.rename(
                os.path.join(work_dir, filename),
                os.path.join(work_dir, newfile)
            )
    print("完成重命名")
    print(os.listdir(work_dir))


xls_to_xlsx('./data')

# 輸出結果:
# ['cut_words.csv', 'email_list.xlsx', 'email_test.docx', 'email_test.jpg', 'email_test.xlsx', 'geo_data.png', 'geo_data.xlsx',
'iotest.txt', 'pyside2.md', 'PySimpleGUI-4.7.1-py3-none-any.whl', 'test.txt', 'test_excel.xlsx', 'ziptest', 'ziptest.zip']
複製代碼

7 定製文件不一樣行

比較兩個文件在哪些行內容不一樣,返回這些行的編號,行號編號從1開始。

定義統計文件行數的函數

# 統計文件個數
    def statLineCnt(statfile):
        print('文件名:'+statfile)
        cnt = 0
        with open(statfile, encoding='utf-8') as f:
            while f.readline():
                cnt += 1
            return cnt
複製代碼

統計文件不一樣之處的子函數:

# more表示含有更多行數的文件
        def diff(more, cnt, less):
            difflist = []
            with open(less, encoding='utf-8') as l:
                with open(more, encoding='utf-8') as m:
                    lines = l.readlines()
                    for i, line in enumerate(lines):
                        if line.strip() != m.readline().strip():
                            difflist.append(i)
            if cnt - i > 1:
                difflist.extend(range(i + 1, cnt))
            return [no+1 for no in difflist]
複製代碼

主函數:

# 返回的結果行號從1開始
# list表示fileA和fileB不一樣的行的編號

def file_diff_line_nos(fileA, fileB):
    try:
        cntA = statLineCnt(fileA)
        cntB = statLineCnt(fileB)
        if cntA > cntB:
            return diff(fileA, cntA, fileB)
        return diff(fileB, cntB, fileA)

    except Exception as e:
        print(e)
複製代碼

比較兩個文件A和B,拿相對較短的文件去比較,過濾行後的換行符\n和空格。

暫未考慮某個文件最後可能有的多行空行等特殊狀況

使用file_diff_line_nos 函數:

if __name__ == '__main__':
    import os
    print(os.getcwd())

    ''' 例子: fileA = "'hello world!!!!''\ 'nice to meet you'\ 'yes'\ 'no1'\ 'jack'" fileB = "'hello world!!!!''\ 'nice to meet you'\ 'yes' " '''
    diff = file_diff_line_nos('./testdir/a.txt', './testdir/b.txt')
    print(diff)  # [4, 5]
複製代碼

關於文件比較的,實際上,在Python中有對應模塊difflib , 提供更多其餘格式的文件更詳細的比較,你們可參考:

docs.python.org/3/library/d…

8 獲取指定後綴名的文件

import os

def find_file(work_dir,extension='jpg'):
    lst = []
    for filename in os.listdir(work_dir):
        print(filename)
        splits = os.path.splitext(filename)
        ext = splits[1] # 拿到擴展名
        if ext == '.'+extension:
            lst.append(filename)
    return lst

r = find_file('.','md') 
print(r) # 返回全部目錄下的md文件
複製代碼

9 批量獲取文件修改時間

# 獲取目錄下文件的修改時間
import os
from datetime import datetime

print(f"當前時間:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

def get_modify_time(indir):
    for root, _, files in os.walk(indir):  # 循環D:\works目錄和子目錄
        for file in files:
            absfile = os.path.join(root, file)
            modtime = datetime.fromtimestamp(os.path.getmtime(absfile))
            now = datetime.now()
            difftime = now-modtime
            if difftime.days < 20:  # 條件篩選超過指定時間的文件
                print(f"""{absfile} 修改時間[{modtime.strftime('%Y-%m-%d %H:%M:%S')}] 距今[{difftime.days:3d}{difftime.seconds//3600:2d}{difftime.seconds%3600//60:2d}]"""
                      )  # 打印相關信息


get_modify_time('./data')
複製代碼
打印效果:
當前時間:2019-12-22 16:38:53
./data\cut_words.csv
                    修改時間[2019-12-21 10:34:15]
                    距今[  1天 6時 4]
當前時間:2019-12-22 16:38:53
./data\cut_words.csv
                    修改時間[2019-12-21 10:34:15]
                    距今[  1天 6時 4]
./data\email_test.docx
                    修改時間[2019-12-03 07:46:29]
                    距今[ 19天 8時52]
./data\email_test.jpg
                    修改時間[2019-12-03 07:46:29]
                    距今[ 19天 8時52]
./data\email_test.xlsx
                    修改時間[2019-12-03 07:46:29]
                    距今[ 19天 8時52]
./data\iotest.txt
                    修改時間[2019-12-13 08:23:18]
                    距今[  9天 8時15]
./data\pyside2.md
                    修改時間[2019-12-05 08:17:22]
                    距今[ 17天 8時21]
./data\PySimpleGUI-4.7.1-py3-none-any.whl
                    修改時間[2019-12-05 00:25:47]
                    距今[ 17天16時13]
複製代碼

10 批量壓縮文件

import zipfile  # 導入zipfile,這個是用來作壓縮和解壓的Python模塊;
import os
import time


def batch_zip(start_dir):
    start_dir = start_dir  # 要壓縮的文件夾路徑
    file_news = start_dir + '.zip'  # 壓縮後文件夾的名字

    z = zipfile.ZipFile(file_news, 'w', zipfile.ZIP_DEFLATED)
    for dir_path, dir_names, file_names in os.walk(start_dir):
        # 這一句很重要,不replace的話,就從根目錄開始複製
        f_path = dir_path.replace(start_dir, '')
        f_path = f_path and f_path + os.sep  # 實現當前文件夾以及包含的全部文件的壓縮
        for filename in file_names:
            z.write(os.path.join(dir_path, filename), f_path + filename)
    z.close()
    return file_news


batch_zip('./data/ziptest')


複製代碼

11 32位加密

import hashlib
# 對字符串s實現32位加密


def hash_cry32(s):
    m = hashlib.md5()
    m.update((str(s).encode('utf-8')))
    return m.hexdigest()


print(hash_cry32(1))  # c4ca4238a0b923820dcc509a6f75849b
print(hash_cry32('hello'))  # 5d41402abc4b2a76b9719d911017c592
複製代碼

5、Python日期

Python日期章節,由表示大日期的calendar, date模塊,逐漸過渡到表示時間刻度更小的模塊:datetime, time模塊,按照此邏輯展開,總結了最經常使用的9個關於時間處理模塊的例子。

1 年的日曆圖

import calendar
year_calendar_str = calendar.calendar(2019)
print(f"{mydate.year}年的日曆圖:{year_calendar_str}\n")
複製代碼

打印結果:

2019

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3                   1  2  3
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       4  5  6  7  8  9 10
14 15 16 17 18 19 20      11 12 13 14 15 16 17      11 12 13 14 15 16 17
21 22 23 24 25 26 27      18 19 20 21 22 23 24      18 19 20 21 22 23 24
28 29 30 31               25 26 27 28               25 26 27 28 29 30 31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7             1  2  3  4  5                      1  2
 8  9 10 11 12 13 14       6  7  8  9 10 11 12       3  4  5  6  7  8  9
15 16 17 18 19 20 21      13 14 15 16 17 18 19      10 11 12 13 14 15 16
22 23 24 25 26 27 28      20 21 22 23 24 25 26      17 18 19 20 21 22 23
29 30                     27 28 29 30 31            24 25 26 27 28 29 30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
 1  2  3  4  5  6  7                1  2  3  4                         1
 8  9 10 11 12 13 14       5  6  7  8  9 10 11       2  3  4  5  6  7  8
15 16 17 18 19 20 21      12 13 14 15 16 17 18       9 10 11 12 13 14 15
22 23 24 25 26 27 28      19 20 21 22 23 24 25      16 17 18 19 20 21 22
29 30 31                  26 27 28 29 30 31         23 24 25 26 27 28 29
                                                    30

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
    1  2  3  4  5  6                   1  2  3                         1
 7  8  9 10 11 12 13       4  5  6  7  8  9 10       2  3  4  5  6  7  8
14 15 16 17 18 19 20      11 12 13 14 15 16 17       9 10 11 12 13 14 15
21 22 23 24 25 26 27      18 19 20 21 22 23 24      16 17 18 19 20 21 22
28 29 30 31               25 26 27 28 29 30         23 24 25 26 27 28 29
                                                    30 31
複製代碼

2 判斷是否爲閏年

import calendar
is_leap = calendar.isleap(mydate.year)
print_leap_str = "%s年是閏年" if is_leap else "%s年不是閏年\n"
print(print_leap_str % mydate.year)
複製代碼

打印結果:

2019年不是閏年
複製代碼

3 月的日曆圖

import calendar
month_calendar_str = calendar.month(mydate.year, mydate.month)
print(f"{mydate.year}年-{mydate.month}月的日曆圖:{month_calendar_str}\n")
複製代碼

打印結果:

December 2019
Mo Tu We Th Fr Sa Su
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
複製代碼

4 月有幾天

import calendar
weekday, days = calendar.monthrange(mydate.year, mydate.month)
print(f'{mydate.year}年-{mydate.month}月的第一天是那一週的第{weekday}天\n')
print(f'{mydate.year}年-{mydate.month}月共有{days}天\n')
複製代碼

打印結果:

2019-12月的第一天是那一週的第62019-12月共有31複製代碼

5 月第一天

from datetime import date
month_first_day = date(mydate.year, mydate.month, 1)
print(f"當月第一天:{month_first_day}\n")
複製代碼

打印結果:

當月第一天:2019-12-01
複製代碼

6 月最後一天

from datetime import date
import calendar
_, days = calendar.monthrange(mydate.year, mydate.month)
month_last_day = date(mydate.year, mydate.month, days)
print(f"當月最後一天:{month_last_day}\n")
複製代碼

打印結果:

當月最後一天:2019-12-31
複製代碼

7 獲取當前時間

from datetime import date, datetime
from time import localtime

today_date = date.today()
print(today_date)  # 2019-12-22

today_time = datetime.today()
print(today_time)  # 2019-12-22 18:02:33.398894

local_time = localtime()
print(strftime("%Y-%m-%d %H:%M:%S", local_time))  # 轉化爲定製的格式 2019-12-22 18:13:41
複製代碼

8 字符時間轉時間

from time import strptime

# parse str time to struct time
struct_time = strptime('2019-12-22 10:10:08', "%Y-%m-%d %H:%M:%S")
print(struct_time) # struct_time類型就是time中的一個類

# time.struct_time(tm_year=2019, tm_mon=12, tm_mday=22, tm_hour=10, tm_min=10, tm_sec=8, tm_wday=6, tm_yday=356, tm_isdst=-1)
複製代碼

9 時間轉字符時間

from time import strftime, strptime, localtime

In [2]: print(localtime()) #這是輸入的時間
Out[2]: time.struct_time(tm_year=2019, tm_mon=12, tm_mday=22, tm_hour=18, tm_min=24, tm_sec=56, tm_wday=6, tm_yday=356, tm_isdst=0)

print(strftime("%m-%d-%Y %H:%M:%S", localtime()))  # 轉化爲定製的格式
# 這是字符串表示的時間: 12-22-2019 18:26:21
複製代碼

6、Python利器

Python中的三大利器包括:迭代器生成器裝飾器,利用好它們才能開發出最高性能的Python程序,涉及到的內置模塊 itertools提供迭代器相關的操做。此部分收錄有意思的例子共計14例。

1 尋找第n次出現位置

def search_n(s, c, n):
    size = 0
    for i, x in enumerate(s):
        if x == c:
            size += 1
        if size == n:
            return i
    return -1



print(search_n("fdasadfadf", "a", 3))# 結果爲7,正確
print(search_n("fdasadfadf", "a", 30))# 結果爲-1,正確
複製代碼

2 斐波那契數列前n項

def fibonacci(n):
    a, b = 1, 1
    for _ in range(n):
        yield a
        a, b = b, a + b


list(fibonacci(5))  # [1, 1, 2, 3, 5]
複製代碼

3 找出全部重複元素

from collections import Counter


def find_all_duplicates(lst):
    c = Counter(lst)
    return list(filter(lambda k: c[k] > 1, c))


find_all_duplicates([1, 2, 2, 3, 3, 3])  # [2,3]
複製代碼

4 聯合統計次數

Counter對象間能夠作數學運算

from collections import Counter
a = ['apple', 'orange', 'computer', 'orange']
b = ['computer', 'orange']

ca = Counter(a)
cb = Counter(b)
#Counter對象間能夠作數學運算
ca + cb  # Counter({'orange': 3, 'computer': 2, 'apple': 1})


# 進一步抽象,實現多個列表內元素的個數統計


def sumc(*c):
    if (len(c) < 1):
        return
    mapc = map(Counter, c)
    s = Counter([])
    for ic in mapc: # ic 是一個Counter對象
        s += ic
    return s


#Counter({'orange': 3, 'computer': 3, 'apple': 1, 'abc': 1, 'face': 1})
sumc(a, b, ['abc'], ['face', 'computer'])

複製代碼

5 groupby單字段分組

天氣記錄:

a = [{'date': '2019-12-15', 'weather': 'cloud'},
 {'date': '2019-12-13', 'weather': 'sunny'},
 {'date': '2019-12-14', 'weather': 'cloud'}]
複製代碼

按照天氣字段weather分組彙總:

from itertools import groupby
for k, items in  groupby(a,key=lambda x:x['weather']):
     print(k)
複製代碼

輸出結果看出,分組失敗!緣由:分組前必須按照分組字段排序,這個很坑~

cloud
sunny
cloud
複製代碼

修改代碼:

a.sort(key=lambda x: x['weather'])
for k, items in  groupby(a,key=lambda x:x['weather']):
     print(k)
     for i in items:
         print(i)
複製代碼

輸出結果:

cloud
{'date': '2019-12-15', 'weather': 'cloud'}
{'date': '2019-12-14', 'weather': 'cloud'}
sunny
{'date': '2019-12-13', 'weather': 'sunny'}
複製代碼

6 itemgetter和key函數

注意到sortgroupby所用的key函數,除了lambda寫法外,還有一種簡寫,就是使用itemgetter

a = [{'date': '2019-12-15', 'weather': 'cloud'},
 {'date': '2019-12-13', 'weather': 'sunny'},
 {'date': '2019-12-14', 'weather': 'cloud'}]
from operator import itemgetter
from itertools import groupby

a.sort(key=itemgetter('weather'))
for k, items in groupby(a, key=itemgetter('weather')):
     print(k)
     for i in items:
         print(i)
複製代碼

結果:

cloud
{'date': '2019-12-15', 'weather': 'cloud'}
{'date': '2019-12-14', 'weather': 'cloud'}
sunny
{'date': '2019-12-13', 'weather': 'sunny'}
複製代碼

7 groupby多字段分組

itemgetter是一個類,itemgetter('weather')返回一個可調用的對象,它的參數可有多個:

from operator import itemgetter
from itertools import groupby

a.sort(key=itemgetter('weather', 'date'))
for k, items in groupby(a, key=itemgetter('weather')):
     print(k)
     for i in items:
         print(i)
複製代碼

結果以下,使用weatherdate兩個字段排序a

cloud
{'date': '2019-12-14', 'weather': 'cloud'}
{'date': '2019-12-15', 'weather': 'cloud'}
sunny
{'date': '2019-12-13', 'weather': 'sunny'}
複製代碼

注意這個結果與上面結果有些微妙不一樣,這個更可能是咱們想看到和使用更多的。

8 sum函數計算和聚合同時作

Python中的聚合類函數sum,min,max第一個參數是iterable類型,通常使用方法以下:

a = [4,2,5,1]
sum([i+1 for i in a]) # 16
複製代碼

使用列表生成式[i+1 for i in a]建立一個長度與a一行的臨時列表,這步完成後,再作sum聚合。

試想若是你的數組a長度十百萬級,再建立一個這樣的臨時列表就很不划算,最好是一邊算一邊聚合,稍改動爲以下:

a = [4,2,5,1]
sum(i+1 for i in a) # 16
複製代碼

此時i+1 for i in a(i+1 for i in a)的簡寫,獲得一個生成器(generator)對象,以下所示:

In [8]:(i+1 for i in a)
OUT [8]:<generator object <genexpr> at 0x000002AC7FFA8CF0>
複製代碼

生成器每迭代一步吐出(yield)一個元素並計算和聚合後,進入下一次迭代,直到終點。

9 list分組(生成器版)

from math import ceil

def divide_iter(lst, n):
    if n <= 0:
        yield lst
        return
    i, div = 0, ceil(len(lst) / n)
    while i < n:
        yield lst[i * div: (i + 1) * div]
        i += 1

list(divide_iter([1, 2, 3, 4, 5], 0))  # [[1, 2, 3, 4, 5]]
list(divide_iter([1, 2, 3, 4, 5], 2))  # [[1, 2, 3], [4, 5]]
複製代碼

10 列表全展開(生成器版)

#多層列表展開成單層列表
a=[1,2,[3,4,[5,6],7],8,["python",6],9]
def function(lst):
    for i in lst:
        if type(i)==list:
            yield from function(i)
        else:
            yield i
print(list(function(a))) # [1, 2, 3, 4, 5, 6, 7, 8, 'python', 6, 9]
複製代碼

11 測試函數運行時間的裝飾器

#測試函數執行時間的裝飾器示例
import time
def timing_func(fn):
    def wrapper():
        start=time.time()
        fn()   #執行傳入的fn參數
        stop=time.time()
        return (stop-start)
    return wrapper
@timing_func
def test_list_append():
    lst=[]
    for i in range(0,100000):
        lst.append(i)  
@timing_func
def test_list_compre():
    [i for i in range(0,100000)]  #列表生成式
a=test_list_append()
c=test_list_compre()
print("test list append time:",a)
print("test list comprehension time:",c)
print("append/compre:",round(a/c,3))

test list append time: 0.0219423770904541
test list comprehension time: 0.007980823516845703
append/compre: 2.749
複製代碼

12 統計異常出現次數和時間的裝飾器

寫一個裝飾器,統計某個異常重複出現指定次數時,經歷的時長。

import time
import math


def excepter(f):
    i = 0
    t1 = time.time()
    def wrapper(): 
        try:
            f()
        except Exception as e:
            nonlocal i
            i += 1
            print(f'{e.args[0]}: {i}')
            t2 = time.time()
            if i == n:
                print(f'spending time:{round(t2-t1,2)}')
    return wrapper

複製代碼

關鍵詞nonlocal經常使用於函數嵌套中,聲明變量i爲非局部變量;

若是不聲明,i+=1代表i爲函數wrapper內的局部變量,由於在i+=1引用(reference)時,i未被聲明,因此會報unreferenced variable的錯誤。

使用建立的裝飾函數excepter, n是異常出現的次數。

共測試了兩類常見的異常:被零除數組越界

n = 10 # except count

@excepter
def divide_zero_except():
    time.sleep(0.1)
    j = 1/(40-20*2)

# test zero divived except
for _ in range(n):
    divide_zero_except()


@excepter
def outof_range_except():
    a = [1,3,5]
    time.sleep(0.1)
    print(a[3])
# test out of range except
for _ in range(n):
    outof_range_except()

複製代碼

打印出來的結果以下:

division by zero: 1
division by zero: 2
division by zero: 3
division by zero: 4
division by zero: 5
division by zero: 6
division by zero: 7
division by zero: 8
division by zero: 9
division by zero: 10
spending time:1.01
list index out of range: 1
list index out of range: 2
list index out of range: 3
list index out of range: 4
list index out of range: 5
list index out of range: 6
list index out of range: 7
list index out of range: 8
list index out of range: 9
list index out of range: 10
spending time:1.01
複製代碼

13 定製遞減迭代器

#編寫一個迭代器,經過循環語句,實現對某個正整數的依次遞減1,直到0.
class Descend(Iterator):
    def __init__(self,N):
        self.N=N
        self.a=0
    def __iter__(self):
        return self 
    def __next__(self):
        while self.a<self.N:
            self.N-=1
            return self.N
        raise StopIteration
    
descend_iter=Descend(10)
print(list(descend_iter))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
複製代碼

核心要點:

1 __nex__名字不能變,實現定製的迭代邏輯

2 raise StopIteration:經過 raise 中斷程序,必須這樣寫

14 測試運行時長的裝飾器

#測試函數執行時間的裝飾器示例
import time
def timing(fn):
    def wrapper():
        start=time.time()
        fn()   #執行傳入的fn參數
        stop=time.time()
        return (stop-start)
    return wrapper

@timing
def test_list_append():
    lst=[]
    for i in range(0,100000):
        lst.append(i)  

@timing
def test_list_compre():
    [i for i in range(0,100000)]  #列表生成式

a=test_list_append()
c=test_list_compre()
print("test list append time:",a)
print("test list comprehension time:",c)
print("append/compre:",round(a/c,3))

# test list append time: 0.0219
# test list comprehension time: 0.00798
# append/compre: 2.749
複製代碼

7、Python畫圖

Python經常使用的繪圖工具包括:matplotlib, seaborn, plotly等,以及一些其餘專用於繪製某類圖如詞雲圖等的包,描繪繪圖軌跡的turtle包等。本章節將會使用一些例子由易到難的闡述繪圖的經典小例子,目前共收錄10個。

1 turtle繪製奧運五環圖

turtle繪圖的函數很是好用,基本看到函數名字,就能知道它的含義,下面使用turtle,僅用15行代碼來繪製奧運五環圖。

1 導入庫

import turtle
複製代碼

2 定義畫圓函數

def drawCircle(x,y,c='red'):
    p.pu()# 擡起畫筆
    p.goto(x,y) # 繪製圓的起始位置
    p.pd()# 放下畫筆
    p.color(c)# 繪製c色圓環
    p.circle(30,360) #繪製圓:半徑,角度
複製代碼

3 畫筆基本設置

p = turtle
p.pensize(3) # 畫筆尺寸設置3
複製代碼

4 繪製五環圖

調用畫圓函數

drawCircle(0,0,'blue')
drawCircle(60,0,'black')
drawCircle(120,0,'red')
drawCircle(90,-30,'green')
drawCircle(30,-30,'yellow')    

p.done()
複製代碼

結果:

[圖片上傳失敗...(image-7c479f-1577689175382)]

2 turtle繪製漫天雪花

導入模塊

導入 turtle庫和 python的 random

import turtle as p
import random
複製代碼

繪製雪花

def snow(snow_count):
    p.hideturtle()
    p.speed(500)
    p.pensize(2)
    for i in range(snow_count):
        r = random.random()
        g = random.random()
        b = random.random()
        p.pencolor(r, g, b)
        p.pu()
        p.goto(random.randint(-350, 350), random.randint(1, 270))
        p.pd()
        dens = random.randint(8, 12)
        snowsize = random.randint(10, 14)
        for _ in range(dens):
            p.forward(snowsize)  # 向當前畫筆方向移動snowsize像素長度
            p.backward(snowsize)  # 向當前畫筆相反方向移動snowsize像素長度
            p.right(360 / dens)  # 順時針移動360 / dens度

複製代碼

繪製地面

def ground(ground_line_count):
    p.hideturtle()
    p.speed(500)
    for i in range(ground_line_count):
        p.pensize(random.randint(5, 10))
        x = random.randint(-400, 350)
        y = random.randint(-280, -1)
        r = -y / 280
        g = -y / 280
        b = -y / 280
        p.pencolor(r, g, b)
        p.penup()  # 擡起畫筆
        p.goto(x, y)  # 讓畫筆移動到此位置
        p.pendown()  # 放下畫筆
        p.forward(random.randint(40, 100))  # 眼當前畫筆方向向前移動40~100距離
複製代碼

主函數

def main():
    p.setup(800, 600, 0, 0)
    # p.tracer(False)
    p.bgcolor("black")
    snow(30)
    ground(30)
    # p.tracer(True)
    p.mainloop()

main()
複製代碼

動態圖結果展現:

Sample

3 wordcloud詞雲圖

import hashlib
import pandas as pd
from wordcloud import WordCloud
geo_data=pd.read_excel(r"../data/geo_data.xlsx")
print(geo_data)
# 0 深圳
# 1 深圳
# 2 深圳
# 3 深圳
# 4 深圳
# 5 深圳
# 6 深圳
# 7 廣州
# 8 廣州
# 9 廣州

words = ','.join(x for x in geo_data['city'] if x != []) #篩選出非空列表值
wc = WordCloud(
    background_color="green", #背景顏色"green"綠色
    max_words=100, #顯示最大詞數
    font_path='./fonts/simhei.ttf', #顯示中文
    min_font_size=5,
    max_font_size=100,
    width=500  #圖幅寬度
    )
x = wc.generate(words)
x.to_file('../data/geo_data.png')
複製代碼

[圖片上傳失敗...(image-78330d-1577689175382)]

4 plotly畫柱狀圖和折線圖

#柱狀圖+折線圖
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(
    go.Scatter(
        x=[0, 1, 2, 3, 4, 5],
        y=[1.5, 1, 1.3, 0.7, 0.8, 0.9]
    ))
fig.add_trace(
    go.Bar(
        x=[0, 1, 2, 3, 4, 5],
        y=[2, 0.5, 0.7, -1.2, 0.3, 0.4]
    ))
fig.show()
複製代碼
Sample

5 seaborn熱力圖

# 導入庫
import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 生成數據集
data = np.random.random((6,6))
np.fill_diagonal(data,np.ones(6))
features = ["prop1","prop2","prop3","prop4","prop5", "prop6"]
data = pd.DataFrame(data, index = features, columns=features)
print(data)
# 繪製熱力圖
heatmap_plot = sns.heatmap(data, center=0, cmap='gist_rainbow')
plt.show()
複製代碼

image.png

6 matplotlib折線圖

模塊名稱:example_utils.py,裏面包括三個函數,各自功能以下:

import matplotlib.pyplot as plt

# 建立畫圖fig和axes
def setup_axes():
    fig, axes = plt.subplots(ncols=3, figsize=(6.5,3))
    for ax in fig.axes:
        ax.set(xticks=[], yticks=[])
    fig.subplots_adjust(wspace=0, left=0, right=0.93)
    return fig, axes
# 圖片標題
def title(fig, text, y=0.9):
    fig.suptitle(text, size=14, y=y, weight='semibold', x=0.98, ha='right',
                 bbox=dict(boxstyle='round', fc='floralwhite', ec='#8B7E66',
                           lw=2))
# 爲數據添加文本註釋
def label(ax, text, y=0):
    ax.annotate(text, xy=(0.5, 0.00), xycoords='axes fraction', ha='center',
                style='italic',
                bbox=dict(boxstyle='round', facecolor='floralwhite',
                          ec='#8B7E66'))
複製代碼

image.png

import numpy as np
import matplotlib.pyplot as plt

import example_utils

x = np.linspace(0, 10, 100)

fig, axes = example_utils.setup_axes()
for ax in axes:
    ax.margins(y=0.10)

# 子圖1 默認plot多條線,顏色系統分配
for i in range(1, 6):
    axes[0].plot(x, i * x)

# 子圖2 展現線的不一樣linestyle
for i, ls in enumerate(['-', '--', ':', '-.']):
    axes[1].plot(x, np.cos(x) + i, linestyle=ls)

# 子圖3 展現線的不一樣linestyle和marker
for i, (ls, mk) in enumerate(zip(['', '-', ':'], ['o', '^', 's'])):
    axes[2].plot(x, np.cos(x) + i * x, linestyle=ls, marker=mk, markevery=10)

# 設置標題
# example_utils.title(fig, '"ax.plot(x, y, ...)": Lines and/or markers', y=0.95)
# 保存圖片
fig.savefig('plot_example.png', facecolor='none')
# 展現圖片
plt.show()
複製代碼

7 matplotlib散點圖

image.png

對應代碼:

""" 散點圖的基本用法 """
import numpy as np
import matplotlib.pyplot as plt

import example_utils

# 隨機生成數據
np.random.seed(1874)
x, y, z = np.random.normal(0, 1, (3, 100))
t = np.arctan2(y, x)
size = 50 * np.cos(2 * t)**2 + 10

fig, axes = example_utils.setup_axes()

# 子圖1
axes[0].scatter(x, y, marker='o',  color='darkblue', facecolor='white', s=80)
example_utils.label(axes[0], 'scatter(x, y)')

# 子圖2
axes[1].scatter(x, y, marker='s', color='darkblue', s=size)
example_utils.label(axes[1], 'scatter(x, y, s)')

# 子圖3
axes[2].scatter(x, y, s=size, c=z,  cmap='gist_ncar')
example_utils.label(axes[2], 'scatter(x, y, s, c)')

# example_utils.title(fig, '"ax.scatter(...)": Colored/scaled markers',
# y=0.95)
fig.savefig('scatter_example.png', facecolor='none')

plt.show()
複製代碼

8 matplotlib柱狀圖

image.png

對應代碼:

import numpy as np
import matplotlib.pyplot as plt

import example_utils


def main():
    fig, axes = example_utils.setup_axes()

    basic_bar(axes[0])
    tornado(axes[1])
    general(axes[2])

    # example_utils.title(fig, '"ax.bar(...)": Plot rectangles')
    fig.savefig('bar_example.png', facecolor='none')
    plt.show()

# 子圖1
def basic_bar(ax):
    y = [1, 3, 4, 5.5, 3, 2]
    err = [0.2, 1, 2.5, 1, 1, 0.5]
    x = np.arange(len(y))
    ax.bar(x, y, yerr=err, color='lightblue', ecolor='black')
    ax.margins(0.05)
    ax.set_ylim(bottom=0)
    example_utils.label(ax, 'bar(x, y, yerr=e)')

# 子圖2
def tornado(ax):
    y = np.arange(8)
    x1 = y + np.random.random(8) + 1
    x2 = y + 3 * np.random.random(8) + 1
    ax.barh(y, x1, color='lightblue')
    ax.barh(y, -x2, color='salmon')
    ax.margins(0.15)
    example_utils.label(ax, 'barh(x, y)')

# 子圖3
def general(ax):
    num = 10
    left = np.random.randint(0, 10, num)
    bottom = np.random.randint(0, 10, num)
    width = np.random.random(num) + 0.5
    height = np.random.random(num) + 0.5
    ax.bar(left, height, width, bottom, color='salmon')
    ax.margins(0.15)
    example_utils.label(ax, 'bar(l, h, w, b)')


main()
複製代碼

9 matplotlib等高線圖

image.png

對應代碼:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.cbook import get_sample_data

import example_utils

z = np.load(get_sample_data('bivariate_normal.npy'))

fig, axes = example_utils.setup_axes()

axes[0].contour(z, cmap='gist_earth')
example_utils.label(axes[0], 'contour')

axes[1].contourf(z, cmap='gist_earth')
example_utils.label(axes[1], 'contourf')

axes[2].contourf(z, cmap='gist_earth')
cont = axes[2].contour(z, colors='black')
axes[2].clabel(cont, fontsize=6)
example_utils.label(axes[2], 'contourf + contour\n + clabel')

# example_utils.title(fig, '"contour, contourf, clabel": Contour/label 2D data',
# y=0.96)
fig.savefig('contour_example.png', facecolor='none')

plt.show()
複製代碼

10 imshow圖

image.png

對應代碼:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.cbook import get_sample_data
from mpl_toolkits import axes_grid1

import example_utils


def main():
    fig, axes = setup_axes()
    plot(axes, *load_data())
    # example_utils.title(fig, '"ax.imshow(data, ...)": Colormapped or RGB arrays')
    fig.savefig('imshow_example.png', facecolor='none')
    plt.show()


def plot(axes, img_data, scalar_data, ny):

    # 默認線性插值
    axes[0].imshow(scalar_data, cmap='gist_earth', extent=[0, ny, ny, 0])

    # 最近鄰插值
    axes[1].imshow(scalar_data, cmap='gist_earth', interpolation='nearest',
                   extent=[0, ny, ny, 0])

    # 展現RGB/RGBA數據
    axes[2].imshow(img_data)


def load_data():
    img_data = plt.imread(get_sample_data('5.png'))
    ny, nx, nbands = img_data.shape
    scalar_data = np.load(get_sample_data('bivariate_normal.npy'))
    return img_data, scalar_data, ny


def setup_axes():
    fig = plt.figure(figsize=(6, 3))
    axes = axes_grid1.ImageGrid(fig, [0, 0, .93, 1], (1, 3), axes_pad=0)

    for ax in axes:
        ax.set(xticks=[], yticks=[])
    return fig, axes


main()
複製代碼

11 pyecharts繪製儀表盤

使用pip install pyecharts 安裝,版本爲 v1.6,pyecharts繪製儀表盤,只須要幾行代碼:

from pyecharts import charts

# 儀表盤
gauge = charts.Gauge()
gauge.add('Python小例子', [('Python機器學習', 30), ('Python基礎', 70.),
                        ('Python正則', 90)])
gauge.render(path="./data/儀表盤.html")
print('ok')
複製代碼

儀表盤中共展現三項,每項的比例爲30%,70%,90%,以下圖默認名稱顯示第一項:Python機器學習,完成比例爲30%

image.png

12 pyecharts漏斗圖

from pyecharts import options as opts
from pyecharts.charts import Funnel, Page
from random import randint

def funnel_base() -> Funnel:
  c = (
    Funnel()
    .add("豪車", [list(z) for z in zip(['寶馬', '法拉利', '奔馳', '奧迪', '大衆', '豐田', '特斯拉'],
                 [randint(1, 20) for _ in range(7)])])
    .set_global_opts(title_opts=opts.TitleOpts(title="豪車漏斗圖"))
  )
  return c
funnel_base().render('./img/car_fnnel.html')
複製代碼

以7種車型及某個屬性值繪製的漏斗圖,屬性值大越靠近漏斗的大端。

image.png

13 pyecharts日曆圖

import datetime
import random
from pyecharts import options as opts
from pyecharts.charts import Calendar

def calendar_interval_1() -> Calendar:
    begin = datetime.date(2019, 1, 1)
    end = datetime.date(2019, 12, 27)
    data = [
        [str(begin + datetime.timedelta(days=i)), random.randint(1000, 25000)]
        for i in range(0, (end - begin).days + 1, 2)  # 隔天統計
    ]
    calendar = (
      Calendar(init_opts=opts.InitOpts(width="1200px")).add(
            "", data, calendar_opts=opts.CalendarOpts(range_="2019"))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="Calendar-2019年步數統計"),
            visualmap_opts=opts.VisualMapOpts(
                max_=25000,
                min_=1000,
                orient="horizontal",
                is_piecewise=True,
                pos_top="230px",
                pos_left="100px",
            ),
        )
    )
    return calendar

calendar_interval_1().render('./img/calendar.html')
複製代碼

繪製2019年1月1日到12月27日的步行數,官方給出的圖形寬度900px不夠,只能顯示到9月份,本例使用opts.InitOpts(width="1200px")作出微調,而且visualmap顯示全部步數,每隔一天顯示一次:

image

14 pyecharts繪製graph圖

import json
import os
from pyecharts import options as opts
from pyecharts.charts import Graph, Page

def graph_base() -> Graph:
    nodes = [
        {"name": "cus1", "symbolSize": 10},
        {"name": "cus2", "symbolSize": 30},
        {"name": "cus3", "symbolSize": 20}
    ]
    links = []
    for i in nodes:
        if i.get('name') == 'cus1':
            continue
        for j in nodes:
            if j.get('name') == 'cus1':
                continue
            links.append({"source": i.get("name"), "target": j.get("name")})
    c = (
        Graph()
        .add("", nodes, links, repulsion=8000)
        .set_global_opts(title_opts=opts.TitleOpts(title="customer-influence"))
    )
    return c
複製代碼

構建圖,其中客戶點1與其餘兩個客戶都沒有關係(link),也就是不存在有效邊:

image

15 pyecharts水球圖

from pyecharts import options as opts
from pyecharts.charts import Liquid, Page
from pyecharts.globals import SymbolType

def liquid() -> Liquid:
    c = (
        Liquid()
        .add("lq", [0.67, 0.30, 0.15])
        .set_global_opts(title_opts=opts.TitleOpts(title="Liquid"))
    )
    return c

liquid().render('./img/liquid.html')
複製代碼

水球圖的取值[0.67, 0.30, 0.15]表示下圖中的三個波浪線,通常表明三個百分比:

image.png

16 pyecharts餅圖

from pyecharts import options as opts
from pyecharts.charts import Pie
from random import randint

def pie_base() -> Pie:
    c = (
        Pie()
        .add("", [list(z) for z in zip(['寶馬', '法拉利', '奔馳', '奧迪', '大衆', '豐田', '特斯拉'],
                                       [randint(1, 20) for _ in range(7)])])
        .set_global_opts(title_opts=opts.TitleOpts(title="Pie-基本示例"))
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
    )
    return c

pie_base().render('./img/pie_pyecharts.html')
複製代碼

image.png

17 pyecharts極座標圖

import random
from pyecharts import options as opts
from pyecharts.charts import Page, Polar

def polar_scatter0() -> Polar:
    data = [(alpha, random.randint(1, 100)) for alpha in range(101)] # r = random.randint(1, 100)
    print(data)
    c = (
        Polar()
        .add("", data, type_="bar", label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(title_opts=opts.TitleOpts(title="Polar"))
    )
    return c

polar_scatter0().render('./img/polar.html')
複製代碼

極座標表示爲(夾角,半徑),如(6,94)表示夾角爲6,半徑94的點:

image.png

18 pyecharts詞雲圖

from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType

words = [
    ("Python", 100),
    ("C++", 80),
    ("Java", 95),
    ("R", 50),
    ("JavaScript", 79),
    ("C", 65)
]

def wordcloud() -> WordCloud:
    c = (
        WordCloud()
        # word_size_range: 單詞字體大小範圍
        .add("", words, word_size_range=[20, 100], shape='cardioid')
        .set_global_opts(title_opts=opts.TitleOpts(title="WordCloud"))
    )
    return c

wordcloud().render('./img/wordcloud.html')
複製代碼

("C",65)表示在本次統計中C語言出現65次

image.png

19 pyecharts系列柱狀圖

from pyecharts import options as opts
from pyecharts.charts import Bar
from random import randint

def bar_series() -> Bar:
    c = (
        Bar()
        .add_xaxis(['寶馬', '法拉利', '奔馳', '奧迪', '大衆', '豐田', '特斯拉'])
        .add_yaxis("銷量", [randint(1, 20) for _ in range(7)])
        .add_yaxis("產量", [randint(1, 20) for _ in range(7)])
        .set_global_opts(title_opts=opts.TitleOpts(title="Bar的主標題", subtitle="Bar的副標題"))
    )
    return c

bar_series().render('./img/bar_series.html')
複製代碼

image.png

20 pyecharts熱力圖

import random
from pyecharts import options as opts
from pyecharts.charts import HeatMap

def heatmap_car() -> HeatMap:
    x = ['寶馬', '法拉利', '奔馳', '奧迪', '大衆', '豐田', '特斯拉']
    y = ['中國','日本','南非','澳大利亞','阿根廷','阿爾及利亞','法國','意大利','加拿大']
    value = [[i, j, random.randint(0, 100)]
             for i in range(len(x)) for j in range(len(y))]
    c = (
        HeatMap()
        .add_xaxis(x)
        .add_yaxis("銷量", y, value)
        .set_global_opts(
            title_opts=opts.TitleOpts(title="HeatMap"),
            visualmap_opts=opts.VisualMapOpts(),
        )
    )
    return c

heatmap_car().render('./img/heatmap_pyecharts.html')
複製代碼

熱力圖描述的實際是三維關係,x軸表示車型,y軸表示國家,每一個色塊的顏色值表明銷量,顏色刻度尺顯示在左下角,顏色越紅表示銷量越大。

image.png

8、Python實戰

1 環境搭建

區分幾個小白容易混淆的概念:pycharm,python解釋器,conda安裝,pip安裝,總結來講:

  • pycharm是python開發的集成開發環境(Integrated Development Environment,簡稱IDE),它自己沒法執行Python代碼
  • python解釋器纔是真正執行代碼的工具,pycharm裏可設置Python解釋器,通常去python官網下載python3.7或python3.8版本;若是安裝過anaconda,它裏面必然也包括一個某版本的Python解釋器;pycharm配置python解釋器選擇哪個均可以。
  • anaconda是python經常使用包的合集,並提供給咱們使用conda命令很是方便的安裝各類Python包。
  • conda安裝:咱們安裝過anaconda軟件後,就可以使用conda命令下載anaconda源裏(好比中科大鏡像源)的包
  • pip安裝:相似於conda安裝的python安裝包的方法

修改鏡像源

在使用安裝conda 安裝某些包會出現慢或安裝失敗問題,最有效方法是修改鏡像源爲國內鏡像源。以前都選用清華鏡像源,可是2019年後已中止服務。推薦選用中科大鏡像源。

先查看已經安裝過的鏡像源,cmd窗口執行命令:

conda config --show
複製代碼

查看配置項channels,若是顯示帶有tsinghua,則說明已安裝過清華鏡像。

channels:
- https://mirrors.tuna.tsinghua.edu.cn/tensorflow/linux/cpu/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
複製代碼

下一步,使用conda config --remove channels url地址刪除清華鏡像,以下命令刪除第一個。而後,依次刪除全部鏡像源

conda config --remove channels https://mirrors.tuna.tsinghua.edu.cn/tensorflow/linux/cpu/
複製代碼

添加目前可用的中科大鏡像源:

conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
複製代碼

並設置搜索時顯示通道地址:

conda config --set show_channel_urls yes
複製代碼

確認是否安裝鏡像源成功,執行conda config --show,找到channels值爲以下:

channels:
  - https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
  - defaults
複製代碼

Done~

2 自動羣發郵件

Python自動羣發郵件

import smtplib
from email import (header)
from email.mime import (text, application, multipart)
import time

def sender_mail():
    smt_p = smtplib.SMTP()
    smt_p.connect(host='smtp.qq.com', port=25)
    sender, password = '113097485@qq.com', "**************"
    smt_p.login(sender, password)
    receiver_addresses, count_num = [
        'guozhennianhua@163.com', 'xiaoxiazi99@163.com'], 1
    for email_address in receiver_addresses:
        try:
            msg = multipart.MIMEMultipart()
            msg['From'] = "zhenguo"
            msg['To'] = email_address
            msg['subject'] = header.Header('這是郵件主題通知', 'utf-8')
            msg.attach(text.MIMEText(
                '這是一封測試郵件,請勿回覆本郵件~', 'plain', 'utf-8'))
            smt_p.sendmail(sender, email_address, msg.as_string())
            time.sleep(10)
            print('第%d次發送給%s' % (count_num, email_address))
            count_num = count_num + 1
        except Exception as e:
            print('第%d次給%s發送郵件異常' % (count_num, email_address))
            continue
    smt_p.quit()

sender_mail()
複製代碼

注意: 發送郵箱是qq郵箱,因此要在qq郵箱中設置開啓SMTP服務,設置完成時會生成一個受權碼,將這個受權碼賦值給文中的password變量。

發送後的截圖:

image.png

3 二分搜索

二分搜索是程序員必備的算法,不管什麼場合,都要很是熟練地寫出來。

小例子描述: 在有序數組arr中,指定區間[left,right]範圍內,查找元素x 若是不存在,返回-1

二分搜索binarySearch實現的主邏輯

def binarySearch(arr, left, right, x):
    while left <= right:

        mid = int(left + (right - left) / 2); # 找到中間位置。求中點寫成(left+right)/2更容易溢出,因此不建議這樣寫

        # 檢查x是否出如今位置mid
        if arr[mid] == x:
            print('found %d 在索引位置%d 處' %(x,mid))
            return mid

            # 假如x更大,則不可能出如今左半部分
        elif arr[mid] < x:
            left = mid + 1 #搜索區間變爲[mid+1,right]
            print('區間縮小爲[%d,%d]' %(mid+1,right))

        # 同理,假如x更小,則不可能出如今右半部分
        elif x<arr[mid]:
            right = mid - 1 #搜索區間變爲[left,mid-1]
            print('區間縮小爲[%d,%d]' %(left,mid-1))

    # 假如搜索到這裏,代表x未出如今[left,right]中
    return -1
複製代碼

Ipython交互界面中,調用binarySearch的小Demo:

In [8]: binarySearch([4,5,6,7,10,20,100],0,6,5)
區間縮小爲[0,2]
found 5 at 1
Out[8]: 1

In [9]: binarySearch([4,5,6,7,10,20,100],0,6,4)
區間縮小爲[0,2]
區間縮小爲[0,0]
found 4 at 0
Out[9]: 0

In [10]: binarySearch([4,5,6,7,10,20,100],0,6,20)
區間縮小爲[4,6]
found 20 at 5
Out[10]: 5

In [11]: binarySearch([4,5,6,7,10,20,100],0,6,100)
區間縮小爲[4,6]
區間縮小爲[6,6]
found 100 at 6
Out[11]: 6
複製代碼

4 爬取天氣數據並解析溫度值

爬取天氣數據並解析溫度值

素材來自朋友袁紹,感謝!

爬取的html 結構

image.png

import requests
from lxml import etree
import pandas as pd
import re

url = 'http://www.weather.com.cn/weather1d/101010100.shtml#input'
with requests.get(url) as res:
    content = res.content
    html = etree.HTML(content)
複製代碼

經過lxml模塊提取值

lxml比beautifulsoup解析在某些場合更高效

location = html.xpath('//*[@id="around"]//a[@target="_blank"]/span/text()')
temperature = html.xpath('//*[@id="around"]/div/ul/li/a/i/text()')
複製代碼

結果:

['香河', '涿州', '唐山', '滄州', '天津', '廊坊', '太原', '石家莊', '涿鹿', '張家口', '保定', '三河', '北京孔廟', '北京國子監', '中國地質博物館', '月壇公
園', '明城牆遺址公園', '北京市規劃展覽館', '什剎海', '南鑼鼓巷', '天壇公園', '北海公園', '景山公園', '北京海洋館']

['11/-5°C', '14/-5°C', '12/-6°C', '12/-5°C', '11/-1°C', '11/-5°C', '8/-7°C', '13/-2°C', '8/-6°C', '5/-9°C', '14/-6°C', '11/-4°C', '13/-3°C'
, '13/-3°C', '12/-3°C', '12/-3°C', '13/-3°C', '12/-2°C', '12/-3°C', '13/-3°C', '12/-2°C', '12/-2°C', '12/-2°C', '12/-3°C']
複製代碼

構造DataFrame對象

df = pd.DataFrame({'location':location, 'temperature':temperature})
print('溫度列')
print(df['temperature'])
複製代碼

正則解析溫度值

df['high'] = df['temperature'].apply(lambda x: int(re.match('(-?[0-9]*?)/-?[0-9]*?°C', x).group(1) ) )
df['low'] = df['temperature'].apply(lambda x: int(re.match('-?[0-9]*?/(-?[0-9]*?)°C', x).group(1) ) )
print(df)
複製代碼

詳細說明子字符創捕獲

除了簡單地判斷是否匹配以外,正則表達式還有提取子串的強大功能。用()表示的就是要提取的分組(group)。好比:^(\d{3})-(\d{3,8})$分別定義了兩個組,能夠直接從匹配的字符串中提取出區號和本地號碼

m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
print(m.group(0))
print(m.group(1))
print(m.group(2))

# 010-12345
# 010
# 12345
複製代碼

若是正則表達式中定義了組,就能夠在Match對象上用group()方法提取出子串來。

注意到group(0)永遠是原始字符串,group(1)group(2)……表示第一、二、……個子串。

最終結果

Name: temperature, dtype: object
    location temperature  high  low
0         香河     11/-5°C    11   -5
1         涿州     14/-5°C    14   -5
2         唐山     12/-6°C    12   -6
3         滄州     12/-5°C    12   -5
4         天津     11/-1°C    11   -1
5         廊坊     11/-5°C    11   -5
6         太原      8/-7°C     8   -7
7        石家莊     13/-2°C    13   -2
8         涿鹿      8/-6°C     8   -6
9        張家口      5/-9°C     5   -9
10        保定     14/-6°C    14   -6
11        三河     11/-4°C    11   -4
12      北京孔廟     13/-3°C    13   -3
13     北京國子監     13/-3°C    13   -3
14   中國地質博物館     12/-3°C    12   -3
15      月壇公園     12/-3°C    12   -3
16   明城牆遺址公園     13/-3°C    13   -3
17  北京市規劃展覽館     12/-2°C    12   -2
18       什剎海     12/-3°C    12   -3
19      南鑼鼓巷     13/-3°C    13   -3
20      天壇公園     12/-2°C    12   -2
21      北海公園     12/-2°C    12   -2
22      景山公園     12/-2°C    12   -2
23     北京海洋館     12/-3°C    12   -3
複製代碼

image.png
相關文章
相關標籤/搜索