1. 程式人生 > >第五篇:python基礎_5

第五篇:python基礎_5

執行過程 ini 間接 ray 復雜 func 時間 基於 time

本篇內容

  1. 協程函數
  2. 遞歸
  3. 二分法
  4. import語句
  5. from...import語句
  6. 模塊搜索路徑
  7. 包的導入
  8. 軟件開發規範
  9. logging模塊的使用

一、 協程函數

1.定義

協程函數就是使用了yield表達式形式的生成器。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def eater(name):
    print("%s eat food" %name)
    while True:
        food = yield

g = eater("yanglei")
print(g)

2.執行過程

運行協程函數,要先next(),對協程函數進行初始化函數,然後再send() ,send會給yield傳一個值。

next()與send()的區別:

next():讓函數初始化。

send():觸發下一次代碼的執行時,會給yield賦值。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def eater(name):
    print(‘%s 說:我開動啦‘ %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food)
        print(‘%s eat %s‘ %(name,food))

def producer():
    alex_g=eater(‘xiaolan‘)
    next(alex_g)
    while True:
        food=input(‘>>: ‘).strip()
        if not food:continue
        print(alex_g.send(food))

producer()

3.裝飾器擴展

協程函數與裝飾器的結合,可以避免忘記初始化函數

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def init(func):
    def wrapper(*args,**kwargs):
        res = func(*args,**kwargs)
        next(res)
        return res
    return wrapper

@init
def eater(name):
    print("%s eat food" %name)
    food_list=[]
    while True:
        food = yield food_list
        print("%s star to eat %s" %(name,food))
        food_list.append(food)

g = eater("xiaolan")

print(g.send("火鍋"))
print(g.send("烤肉"))
print(g.send("烤魚"))

4.面向過程應用

面向過程:核心是過程二字,過程即解決問題的步驟,基於面向過程去設計程序就像是在設計一條工業流水線,是一種機械式的思維方式。

優點:程序結構清晰,可以把復雜的問題簡單化,流程化。

缺點:可擴展性差,一條流線只是用來解決一個問題。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

#grep -rl ‘error‘ /dir/
import os
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

#第一階段:找到所有文件的絕對路徑
@init
def search(target):
    while True:
        filepath=yield
        g=os.walk(filepath)
        for pardir,_,files in g:
            for file in files:
                abspath=r‘%s\%s‘ %(pardir,file)
                target.send(abspath)

#第二階段:打開文件
@init
def opener(target):
    while True:
        abspath=yield
        with open(abspath,‘rb‘) as f:
            target.send((abspath,f))

#第三階段:循環讀出每一行內容
@init
def cat(target):
    while True:
        abspath,f=yield #(abspath,f)
        for line in f:
            res=target.send((abspath,line))
            if res:break

#第四階段:過濾
@init
def grep(pattern,target):
    tag=False
    while True:
        abspath,line=yield tag
        tag=False
        if pattern in line:
            target.send(abspath)
            tag=True

#第五階段:打印該行屬於的文件名
@init
def printer():
    while True:
        abspath=yield
        print(abspath)

g = search(opener(cat(grep(‘error‘.encode(‘utf-8‘), printer()))))
g.send(r‘F:\python\s18‘)

二、 遞歸

1.遞歸調用

在調用一個函數的過程中,直接或間接地調用了函數本身,我們稱為遞歸的調用。

(1)直接調用

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def func():
    print(‘the is func‘)
    func()

func()

(2)間接調用

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def foo():
    print(‘the is foo‘)
    bar()

def bar():
    print(‘the is bar‘)
    foo()

foo()

2.遞歸的執行

遞歸的執行分為兩個階段遞推和回溯。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

def age(n):
    if n == 1:
        return 18
    return age(n-1)+2

print(age(5))

技術分享

三、 二分法

算法:當數據量很大適宜采用該方法。采用二分法查找時,數據需是排好序的。主要思想是:(設查找的數組區間為array[low, high])。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

l = [1,2,5,7,10,31,44,47,56,99,102,130,240]
def binary_search(l,num):
    print(l)
    if len(l) > 1:
        mid_index=len(l)//2
        if num > l[mid_index]:
            #in the right
            l=l[mid_index:]
            binary_search(l,num)
        elif num < l[mid_index]:
            #in the left
            l=l[:mid_index]
            binary_search(l,num)
        else:
            print(‘find it‘)
    else:
        if l[0] == num:
            print(‘find it‘)
        else:
            print(‘not exist‘)
        return

binary_search(l,31)

四、import語句

1.執行源文件。
2.以一個源文件的全局名稱空間。
3.在當前位置拿到一個模塊名,指向2創建的名稱空間。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

print(‘from the spam.py‘)
money=0
x=1
def read1():
    print(‘spam->read1->money‘,money)

def read2():
    print(‘spam->read2 calling read‘)
    read1()

def change():
    global money
    money=0

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import spam

money=100000000000
def read1():
    print(‘from test‘)

print(spam.money)
print(spam.read1)
spam.read1()

spam.read2()
spam.change()
print(money)
spam.read1()

import spam as s1
print(s1.money)

五、from...import語句

優點:使用源文件內的名字時無需加前綴,使用方便。
缺點:容易與當前文件的名稱空間內的名字混淆。

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

print(‘from the spam.py‘)
money=0
x=1
def read1():
    print(‘spam->read1->money‘,money)

def read2():
    print(‘spam->read2 calling read‘)
    read1()

def change():
    global money
    money=0

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

from spam import money,read1,read2,change

money=0
print(money)
print(read1)

read1()

def read1():print(‘ok‘)
read2()

money=10
change()
print(money)

from spam import money as m

print(m)

六、模塊搜索路徑

註意:自定義的模塊名一定不要與python自帶的模塊名重名
內存中---> 內置模塊---> sys.path

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

print(‘from the spam.py‘)
money=0
x=1
def read1():
    print(‘spam->read1->money‘,money)

def read2():
    print(‘spam->read2 calling read‘)
    read1()

def change():
    global money
    money=0

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import time
import importlib

import spam
time.sleep(20)
import spam
print(spam.money)

importlib.reload(spam)
print(spam.money)


 
import sys
print(‘time‘ in sys.modules)
import time
print(‘time‘ in sys.modules)

當spam在別的路徑時

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import sys
# print(sys.path)
sys.path.insert(0,r‘F:\python\s18\day5\test‘)


import spam

七、包的導入

(1)無論是import形式還是from...import形式,凡是在導入語句中(而不是在使用時)遇到帶點的,都要第一時間提高警覺:這是關於包才有的導入語法

(2)包是目錄級的(文件夾級),文件夾是用來組成py文件(包的本質就是一個包含__init__.py文件的目錄)

(3)import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字同樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件

1.絕對導入

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import sys
print(sys.path)
sys.path.append(r‘F:\python\s18\day5‘)
import aaa

print(aaa)
print(aaa.x)
print(aaa.y)

aaa.m1.func1()

aaa.bbb.m3.func3()
 

aaa.func1()
aaa.func2()
aaa.func3()

import aaa.bbb.m3 as abm
abm.func3()

2.相對導入

#!/usr/binl/env python
#encoding: utf-8
#author: YangLei

import sys
sys.path.append(r‘C:\Users\Administrator\PycharmProjects\python18期周末班\day5\a‘)

import glance_v1

glance_v1.get()
glance_v1.create_resource(‘test.conf‘)
glance_v1.main()
glance_v1.register_models(‘mysql‘)

八、軟件開發規範

技術分享

以項目來命名,項目文件夾中要包含bin文件夾、conf文件夾、core文件夾、db文件夾、lib文件夾、log文件夾和readme。

九、logging模塊的使用

1.使用方法

(1)如果不指定filename,則默認打印到終端

(2)指定日誌級別:

指定方式:
1:level=10
2:level=logging.ERROR

日誌級別種類:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
(3)指定日誌級別為ERROR,則只有ERROR及其以上級別的日誌會被打印

logging.basicConfig(filename=‘access.log‘,
                    format=‘%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s‘,
                    datefmt=‘%Y-%m-%d %H:%M:%S %p‘,
                    level=10)

logging.debug(‘debug‘)
logging.info(‘info‘)
logging.warning(‘warning‘)
logging.error(‘error‘)
logging.critical(‘critical‘)
logging.log(10,‘log‘)

2.自定義logging

"""
logging配置
"""

import os
import logging.config

# 定義三種日誌輸出格式 開始

standard_format = ‘[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]‘                   ‘[%(levelname)s][%(message)s]‘ #其中name為getlogger指定的名字

simple_format = ‘[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s‘

id_simple_format = ‘[%(levelname)s][%(asctime)s] %(message)s‘

# 定義日誌輸出格式 結束

logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目錄

logfile_name = ‘all2.log‘  # log文件名

# 如果不存在定義的日誌目錄就創建一個
if not os.path.isdir(logfile_dir):
    os.mkdir(logfile_dir)

# log文件的全路徑
logfile_path = os.path.join(logfile_dir, logfile_name)

# log配置字典
LOGGING_DIC = {
    ‘version‘: 1,
    ‘disable_existing_loggers‘: False,
    ‘formatters‘: {
        ‘standard‘: {
            ‘format‘: standard_format
        },
        ‘simple‘: {
            ‘format‘: simple_format
        },
    },
    ‘filters‘: {},
    ‘handlers‘: {
        #打印到終端的日誌
        ‘console‘: {
            ‘level‘: ‘DEBUG‘,
            ‘class‘: ‘logging.StreamHandler‘,  # 打印到屏幕
            ‘formatter‘: ‘simple‘
        },
        #打印到文件的日誌,收集info及以上的日誌
        ‘default‘: {
            ‘level‘: ‘DEBUG‘,
            ‘class‘: ‘logging.handlers.RotatingFileHandler‘,  # 保存到文件
            ‘formatter‘: ‘standard‘,
            ‘filename‘: logfile_path,  # 日誌文件
            ‘maxBytes‘: 1024*1024*5,  # 日誌大小 5M
            ‘backupCount‘: 5,
            ‘encoding‘: ‘utf-8‘,  # 日誌文件的編碼,再也不用擔心中文log亂碼了
        },
    },
    ‘loggers‘: {
        #logging.getLogger(__name__)拿到的logger配置
        ‘‘: {
            ‘handlers‘: [‘default‘, ‘console‘],  # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕
            ‘level‘: ‘DEBUG‘,
            ‘propagate‘: True,  # 向上(更高level的logger)傳遞
        },
    },
}


def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)  # 導入上面定義的logging配置
    logger = logging.getLogger(__name__)  # 生成一個log實例
    logger.info(‘It works!‘)  # 記錄該文件的運行狀態

if __name__ == ‘__main__‘:
    load_my_logging_cfg()

logging配置文件

第五篇:python基礎_5