1 user_info = {} 2 3 4 def check_login(func): 5 def inner(*args, **kwargs): 6 if user_info.get('is_login', None): 7 ret = func(*args, **kwargs) 8 return ret 9 else: 10 print('請先登陸...') 11 return inner 12 13 14 def check_user_type(func): 15 def inner(*args, **kwargs): 16 if user_info.get('user_type', None) == 1: 17 ret = func(*args, **kwargs) 18 return ret 19 else: 20 print('無權限查看...') 21 return inner 22 23 24 def login(): 25 user = input('請輸入用戶名: ') 26 if user == 'admin': 27 user_info['is_login'] = True 28 user_info['user_type'] = 1 29 else: 30 user_info['is_login'] = True 31 user_info['user_type'] = 2 32 33 @check_login 34 @check_user_type 35 def index(): 36 """ 37 管理員的功能 38 :return: 39 """ 40 print('index') 41 42 @check_login 43 def home(): 44 """ 45 普通用戶的功能 46 :return: 47 """ 48 print('home') 49 50 51 def main(): 52 while True: 53 int = input('1. 登陸 2.查看信息 3.超級管理員\n>>>') 54 if int == '1': 55 login() 56 elif int == '2': 57 home() 58 elif int == '3': 59 index() 60 61 62 main()
注意:雙層裝飾器的執行過程html
目前python支持百分號和format來完成字符串格式化的操做,百分號是2.0版本的。format方式是3.0版本的。python
format支持的格式比百分號方式多。算法
一、百分號方式json
1 str = "my name is %s, age is %d" 2 print(str%('john', 23))
%[(name)][flags][width].[precision]typecode數據結構
注:Python中百分號格式化是不存在自動將整數轉換成二進制表示的方式app
經常使用格式化ide
1 tpl = "i am %s" % "john" 2 3 tpl = "i am %s age %d" % ("john", 18) 4 5 tpl = "i am %(name)s age %(age)d" % {"name": "john", "age": 18} 6 7 tpl = "percent %.2f" % 99.97623 8 9 tpl = "i am %(pp).2f" % {"pp": 123.425556, } 10 11 tpl = "i am %.2f %%" %123.425556
format方式函數
1 str = "my name is {0}, age is {1}" 2 print(str.format('john',25))
[[fill]align][sign][#][0][width][,][.precision][type]this
經常使用格式化:spa
1 tpl = "i am {}, age {}, {}".format("john", 25, 'john') 2 3 tpl = "i am {}, age {}, {}".format(*["john", 25, 'john']) 4 5 tpl = "i am {0}, age {1}, really {0}".format("john", 25) 6 7 tpl = "i am {0}, age {1}, really {0}".format(*["john", 25]) 8 9 tpl = "i am {name}, age {age}, really {name}".format(name="john", age=25) 10 11 tpl = "i am {name}, age {age}, really {name}".format(**{"name": "john", "age": 25}) 12 13 tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format(['john', 25, 'john'], [11, 22, 33]) 14 15 tpl = "i am {:s}, age {:d}, money {:f}".format("john", 25, 88888.1) 16 17 tpl = "i am {:s}, age {:d}".format(*["john", 25]) 18 19 tpl = "i am {name:s}, age {age:d}".format(name="john", age=25) 20 21 tpl = "i am {name:s}, age {age:d}".format(**{"name": "john", "age": 25}) 22 23 tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) 24 25 tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) 26 27 tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15) 28 29 tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)
更多格式化操做:https://docs.python.org/3/library/string.html
一、生成器Generators
生成器是一個有生成數據能力的對象。函數中若是用到了yield語法,那麼這個函數就是一個生成器
特色:
yield 生成器的運行機制:
當你問生成器要一個數時,生成器會執行,直至出現 yield 語句,生成器把 yield 的參數給你,以後生成器就不會往下繼續運行。 當你問他要下一個數時,他會從上次的狀態。開始運行,直至出現yield語句,把參數給你,以後停下。如此反覆,直至退出函數。
yield的使用:
1 def xf(): 2 yield 1 3 yield 2 4 yield 3 5 6 ret = xf() 7 print(ret.__next__()) 8 print(ret.__next__()) 9 print(ret.__next__()) 10 print(ret.__next__()) 11 12 結果: 13 14 1 15 2 16 3 17 File "/Users/TheOne/PycharmProjects/s13/day5/day5-課上/module.py", line 15, in <module> 18 print(ret.__next__()) 19 StopIteration
二、迭代器Iterators
迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到全部的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,由於人們不多在迭代途中日後退。
優勢:
說明:for循環內部就是使用了next方法實現了遍歷
1 def fo(arg): 2 arg += 1 3 if arg >= 5: 4 print(arg) 5 else: 6 return fo(arg) 7 fo(1) 8 9 結果: 10 5
若是函數包含了對其自身的調用,該函數就是遞歸的。
這裏插入一些關於遞歸的網方解釋,由於我是從網上搜到的這些內容:
(1)遞歸就是在過程或函數裏調用自身;
(2)在使用遞歸策略時,必須有一個明確的遞歸結束條件,稱爲遞歸出口。
遞歸算法通常用於解決三類問題:
(1)數據的定義是按遞歸定義的。(好比Fibonacci函數)
(2)問題解法按遞歸算法實現。(回溯)
(3)數據的結構形式是按遞歸定義的。(好比樹的遍歷,圖的搜索)
遞歸的缺點:遞歸算法解題的運行效率較低。在遞歸調用的過程中系統爲每一層的返回點、局部量等開闢了棧來存儲。遞歸次數過多容易形成棧溢出等。
參考:http://www.cnblogs.com/balian/archive/2011/02/11/1951054.html
爲何要有模塊?
如今,咱們寫一些小項目時,都喜歡把全部的函數都放在一個文件裏面(.py)。那麼若是之後寫大型項目,涉及到的函數可能有幾百幾千個,那個時候咱們若是要更改某個函數的函數功能。缺點以下:
爲了解決上面的難題,就用到了模塊,模塊和普通的程序同樣,只不過模塊文件中存放的所有都是業務處理的惟一功能,好比。用戶操做的函數寫在一個文件中,後臺管理類的函數放在一個文件中。在主程序須要用到的時候,直接導入模塊,執行對應的函數功能便可。優勢以下:
導入模塊的依據
模塊的導入都是針對當前執行程序的目錄而言的,python會先到當前程序執行的目錄去查找模塊,若是找不到,會接着到python定義的幾個目錄中去查找。若是還找不到,那麼就會報錯。
1 import sys 2 for i in sys.path: 3 print(i) 4 結果: 5 /Users/TheOne/PycharmProjects/s13/day5/day5-課上 6 /Users/TheOne/PycharmProjects/s13 7 /Library/Frameworks/Python.framework/Versions/3.5/lib/python35.zip 8 /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5 9 /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/plat-darwin 10 /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload 11 /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages
python將全部的查找路徑都放到了sys.path中以列表的方式保存,若是咱們想到除以上路徑外的其它地方加載模塊,那麼將模塊的目錄append到sys.path中便可。
模塊名稱的重要性
爲了不自定義模塊和系統或第三方模塊的name衝突,在自定義模塊的時候,要儘可能避開系統模塊名 。或者爲自定義模塊賦予別名。
模塊的導入方法
一、若是在同一目錄下:
import 模塊名
二、在當前目錄下的其它目錄
from 目錄名 import 模塊名
三、導入模塊並命名別名
from 目錄名 import 模塊名 as 別名
json(適合全部程序語言,能夠跨語言平臺,用來在不一樣語言平臺中交換數據。json只支持基本數據類型,即字符串,字典,列表,元素,數字等)
功能:
1 將python數據類型序列化成字符串 2 3 import json 4 dic = {'name':'john','age':25} 5 print(dic, type(dic)) 6 ret = json.dumps(dic) 7 print(ret, type(ret)) 8 結果: 9 {'age': 25, 'name': 'john'} <class 'dict'> 10 {"age": 25, "name": "john"} <class 'str'> 11 12 將字符串反序列化成python數據類型 13 import json 14 dic = '{"name":"john","age":25}' 15 print(dic, type(dic)) 16 ret = json.loads(dic) 17 print(ret, type(ret)) 18 結果: 19 {"name":"john","age":25} <class 'str'> 20 {'age': 25, 'name': 'john'} <class 'dict'>
注意:將字符串反序列化成python數據類型,必定要用單引號,不然報錯。由於,在其餘語言平臺,單引號的叫字符,雙引號的叫字符串
1 將python數據序列化到文件中 2 import json 3 dic = {"name":"john","age":25} 4 json.dump(dic, open('db', 'w')) 5 6 從文件中反序列化到python 7 ret = json.load(open('db', 'r')) 8 print(ret, type(ret)) 9 結果: 10 {'name': 'john', 'age': 25} <class 'dict'>
pickle(支持python中的任意數據類型,基本數據類型和對象等。只能在python中使用,不支持跨語言平臺使用)
功能和json同樣,只不過pickle在序列化時,將python數據轉換成了pickle的特定格式。
功能:
time&datetime模塊
#_*_coding:utf-8_*_ import time import datetime print(time.clock()) #返回處理器時間,3.3開始已廢棄 print(time.process_time()) #返回處理器時間,3.3開始已廢棄 print(time.time()) #返回當前系統時間戳 print(time.ctime()) #輸出Tue Jan 26 18:23:48 2016 ,當前系統時間 print(time.ctime(time.time()-86640)) #將時間戳轉爲字符串格式 print(time.gmtime(time.time()-86640)) #將時間戳轉換成struct_time格式 print(time.localtime(time.time()-86640)) #將時間戳轉換成struct_time格式,但返回 的本地時間 print(time.mktime(time.localtime())) #與time.localtime()功能相反,將struct_time格式轉回成時間戳格式 #time.sleep(4) #sleep print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #將struct_time格式轉成指定的字符串格式 print(time.strptime("2016-01-28","%Y-%m-%d") ) #將字符串格式轉換成struct_time格式 #datetime module print(datetime.date.today()) #輸出格式 2016-01-26 print(datetime.date.fromtimestamp(time.time()-864400) ) #2016-01-16 將時間戳轉成日期格式 current_time = datetime.datetime.now() # print(current_time) #輸出2016-01-26 19:04:30.335935 print(current_time.timetuple()) #返回struct_time格式 #datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]) print(current_time.replace(2014,9,12)) #輸出2014-09-12 19:06:24.074900,返回當前時間,但指定的值將被替換 str_to_date = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #將字符串轉換成日期格式 new_date = datetime.datetime.now() + datetime.timedelta(days=10) #比如今加10天 new_date = datetime.datetime.now() + datetime.timedelta(days=-10) #比如今減10天 new_date = datetime.datetime.now() + datetime.timedelta(hours=-10) #比如今減10小時 new_date = datetime.datetime.now() + datetime.timedelta(seconds=120) #比如今+120s print(new_date)
loggin模塊
不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug()
, info()
, warning()
, error()
and critical() 5個級別,
下面咱們看一下怎麼用。
loggin模塊級別
Level | When it’s used |
---|---|
DEBUG |
Detailed information, typically of interest only when diagnosing problems. |
INFO |
Confirmation that things are working as expected. |
WARNING |
An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR |
Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL |
A serious error, indicating that the program itself may be unable to continue running. |
若是想把日誌寫到文件裏,也很簡單
1 import logging 2 3 logging.basicConfig(filename='example.log',level=logging.INFO) 4 logging.debug('This message should go to the log file') 5 logging.info('So should this') 6 logging.warning('And this, too')
|
其中下面這句中的level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏,在這個例子, 第一條日誌是不會被紀錄的,若是但願紀錄debug的日誌,那把日誌級別改爲DEBUG就好了。
1 logging.basicConfig(filename='example.log',level=logging.INFO)
感受上面的日誌格式忘記加上時間啦,日誌不知道時間怎麼行呢,下面就來加上!
1 import logging 2 logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') 3 logging.warning('is when this event was logged.') 4 5 #輸出 6 12/12/2010 11:46:36 AM is when this event was logged.
若是想同時把log打印在屏幕和文件日誌裏,就須要瞭解一點複雜的知識 了
The logging library takes a modular approach and offers several categories of components: loggers, handlers, filters, and formatters.
1 import logging 2 3 #create logger 4 logger = logging.getLogger('TEST-LOG') 5 logger.setLevel(logging.DEBUG) 6 7 8 # create console handler and set level to debug 9 ch = logging.StreamHandler() 10 ch.setLevel(logging.DEBUG) 11 12 # create file handler and set level to warning 13 fh = logging.FileHandler("access.log") 14 fh.setLevel(logging.WARNING) 15 # create formatter 16 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 17 18 # add formatter to ch and fh 19 ch.setFormatter(formatter) 20 fh.setFormatter(formatter) 21 22 # add ch and fh to logger 23 logger.addHandler(ch) 24 logger.addHandler(fh) 25 26 # 'application' code 27 logger.debug('debug message') 28 logger.info('info message') 29 logger.warn('warn message') 30 logger.error('error message') 31 logger.critical('critical message')