文章目錄
python安裝、數據類型、函數及變長參數等基本知識不再贅述,下面從最基礎的迭代器開始學習。
(這篇主要是函數與類相關的知識)
1、迭代器
#樣例1iter
list1 = [1,2,3]
it = iter(list1)
print(next(it))
print(next(it))
#樣例2yield---生成器,迭代器的一種
def frange(start,stop,step):
x = start
while x<stop:
yield x#暫停以記錄x的值
x+= step
for i in frange(10,20,0.5):
print(i)
2、lambda表達式
#lambda表達式前面是參數,後面是return內容
def true():
return True##複雜,可使用lambda表達式簡化
lambda : True
def add(x,y):
return x+y
lambda x,y: x+y
def func(x):
return x<=1
lambda x:x<=1
3、內建函數filter,map,reduce,zip
a = [1,2,3,4,5]
b = [6,7,8,9,10]
#filter選出a中滿足函數要求的數,返回filter對象
print(list(filter(lambda x: x > 2, a)))
#map對比較參數依此處理,返回的是map對象
print(list(map(lambda x: x+1, a)))
print(list(map(lambda x, y: x+y, a, b)))#實現a,b中每個元素依次相加,輸出[7, 9, 11, 13, 15]
from functools import reduce
print(reduce(lambda x, y: x*y, [2,3,4], 1))#4*((1*2)*3)=24
for i in zip((1,2,3), (4,5,6)):
print(i)#這裏的作用類似於矩陣,輸出(1, 4)(2, 5)(3, 6)
dicta = {'a': 'aa', 'b': 'bb'}
dictb = zip(dicta.values(), dicta.keys())#相當於將字典的key和value對調,返回的是zip類型
print(dict(dictb))#轉換爲dict後輸出,{'aa': 'a', 'bb': 'b'}
4、閉包的定義
閉包:外部函數的變量被內部函數引用的方式
例中add—函數的名稱或引用;add()函數的調用
#(觀察得一個閉包最後返回的是內層函數的*引用or名稱*)
def sum(a):
def add(b):
return a+b
return add
**#add---函數的名稱或引用;add()函數的調用**
num = sum(2)
print(num(4))#6
#閉包實現遞增的操作,傳入值就爲FIRST,默認是0
def counter(FIRST=0):
cnt = [FIRST]
def add_one():
cnt[0] +=1
return cnt[0]
return add_one
num5 = counter(5)#從5開始
num10 = counter(10)
print(num5())#6
print(num5())#再運行一次又加1,輸出7
print(num10())#11
print(num10())#12
5、閉包的使用
使用閉包的好處:調用的參數比普通函數少,代碼優雅。
#例題:解決a*x+b=y,
def a_line(a,b):
def arg_y(x):
return a*x+b
return arg_y
line1 = a_line(3,5)
line2 = a_line(5,10)
print(line1(10))#35
print(line2(10))#60
6、裝飾器
(與閉包不同的是,閉包外層參數是數,裝飾器外層參數是函數)
優點:
- 調用函數時不用重複在代碼上邊下面編寫相應修飾代碼,可以放在裝飾器裏;
- 裝飾器的代碼複用可以用”@裝飾器名稱“來進行重複調用,語法更簡潔
#1)計時器示例
import time
def timmer(func):
def wapper():
start_time = time.time()
func()
stop_time = time.time()
print("運行時間:%s秒"%(stop_time - start_time))
return wapper
@timmer
def i_can_sleep():
time.sleep(3)
#調用函數
i_can_sleep()#輸出:運行時間:3.0513498783111572秒
#2)實現內部函數帶參數
def tips(func):
def nei(a,b):
print("start!")
func(a,b)
print("stop!")
return nei
@tips
def add(a, b):
print(a+b)
@tips
def sub(a, b):
print(a-b)
print(add(4, 5))
輸出:
start!
9
stop!
None
start!
2
stop!
None
#3)2的基礎上裝飾器帶參數(外層再嵌套new_tips)
def new_tips(argv):
def tips(func):
def nei(a, b):
print("start! %s %s"%(argv, func.__name__))
#func.__name__取運行的函數名稱
func(a, b)
print("stop!")
return nei
return tips
@new_tips("add_module")
def add(a, b):
print(a + b)
@new_tips("sub_module")
def sub(a, b):
print(a - b)
print(add(4, 5))
print(sub(7, 5))
輸出:
s tart! add_module 函數名稱:add
9
stop! None start! sub_module 函數名稱:sub
2
stop!
None
7、上下文管理器(附異常捕獲)
文件操作是python常用操作,需要捕獲異常,常規寫法爲:
try:
a = open('name.txt')
for line in fd:
print(line)
except Exception as e:
print(e)
finally:
a.close()
簡化版,其中with的操作會自動調用finally中的close()的操作,優雅的多。這就是一種上下文管理器
with open("name.txt") as f:
for line in f:
print(line)
8、模塊的定義
自己編寫的函數希望下次繼續使用就可以以模塊的形式對其進行保存。
首先兩個文件,一個是mymod.py,定義函數等
def print_me():
print("me!")
另一個文件,mod_test.py,調用剛定義的模塊
import mymod
mymod.print_me()#輸出:me
9、PEP8編碼規範
有用的插件:autopep8安裝教程:
python代碼一鍵格式化,符合pep8規範
10、類與實例
面向對象編程,幾點總結:
- 定義類,類名首字母大寫;
- 引用類叫做類的實例化;
- 類中實現的函數功能叫做定義類的方法;變量稱爲屬性;
- 是把相同的內容進行一些歸納,更符合人的思維習慣
- 特殊關鍵字:self:表示類實例化的本身(類中使用變量時必須要帶);__init__是一個特殊方法,對類進行實例化後會自動執行。
class Player():
def __init__(self, name, hp):#此方法中預定義了一些功能
self.name = name#**使用變量時必須要帶self**
self.hp = hp
def print_role(self):#定義一個方法
print('%s: %s' % (self.name, self.hp))
user1 = Player('Tom', 100)#類到具體對象的過程叫類的實例化
user2 = Player('Jerry', 90)
user1.print_role()#示例調用方法
user2.print_role()
Tom: 100
Jerry: 90
11、增加類的屬性與方法(附類封裝特性)
增加一個occu職位屬性和updateName()方法。
注意:此時修改名稱除了使用updateName()還可以直接賦值,例如賦值’aaa’。如果將第三行的name改爲__name,則只能通過調用方法改變,不可隨意賦值改變 ------這稱爲類的封裝!
class Player():
def __init__(self, name, hp, occu): # 此方法中預定義了一些功能
self.name = name # 使用變量時必須要帶self
self.hp = hp
self.occu = occu
def print_role(self): # 定義一個方法
print('%s: %s %s' % (self.name, self.hp, self.occu))
def updateName(self, newname):#修改名稱
self.name = newname
user1 = Player('Tom', 100,'war') # 類到具體對象的過程叫類的實例化
user2 = Player('Jerry', 90,'master')
user1.print_role()
user2.print_role()
user1.updateName('Wilson')#user1改名
user1.print_role()
user1.name='aaa'#還可以直接賦值
user1.print_role()
Tom: 100 war
Jerry: 90 master
wilson: 100 war
aaa: 100 war#此時賦值是可以的
12、類的繼承(附多態)
子類可以繼承父類中的方法,當方法同名會發生覆蓋;即當你使用時才能知道運行的時哪一種方法,說明方法有多種狀態,這也是面向對象的一個特性-----多態;
在下面例子中,有以下要點:
- 使用super,子類調用父類的__init__初始化函數,括號是需要的參數
- **type()**方法判斷實例所屬的類
- isinstance(a2,Monster)方法判斷a2是否屬於Monster類。在終端調式可以發現python所有的類型都是object類的子類,例如:
class Monster():
def __init__(self, hp=100): # 默認值,初始化100
self.hp = hp
def run(self):
print("Move!")
class Animals(Monster):
def __init__(self, hp=10):
super().__init__(hp)#使用super不需要重複使用self.hp=hp
a1 = Monster(200)
print(a1.hp)
print(a1.run())
a2 = Animals(1)
print(a2.hp)
print(a2.run())
print("a1的類型:%s"%(type(a1)))
print(isinstance(a2,Monster))
200
Move!
None
1
Move!
None
a1的類型:<class ‘main.Monster’>
True
13、類的使用(自定義with語句)
下面的例子實際就是把類的功能和拋出異常結合起來。
exc_tb是__exit__中捕獲的異常。
#類使用,自定義with
class Testwith():
def __enter__(self):
print('run!')
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_tb is None:#即沒有異常
print('正常結束!')
else:
print('has error:%s'%exc_tb)#輸出錯誤
with Testwith():
print('Test is running')
run!
Test is running
正常結束!
如果有異常是什麼樣?我們可以在with後面手動拋出異常(使用raise),常見的是NameError:
raise NameError('testNameError')#手動拋出異常