2018年11月29日 星期四

pytthon - re模塊

.RE模塊
.正則表達式 -字符串匹配 

.學習使用RE模塊來操作正則表達式


使用普通循環
while True:
    phone_number = input('please input your phone number : ')
    if len(phone_number) == 11\
            and phone_number.isdigit()\
            and (phone_number.startswith('13') \
            or phone_number.startswith('14') \
            or phone_number.startswith('15') \
            or phone_number.startswith('18')):
        print('是合法的手机号码')
    else:
        print('不是合法的手机号码')

使用正則表達式
import re
phone_number =  input("請輸入你的手機號碼(please input your  phone number):")
if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
    print('是合法的手机号码')
else:
    print('不是合法的手机号码')









2018年11月25日 星期日

python - 二分查找方法



l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]


def find(l,aim,start = 0,end = None):
    end = len(l) if end is None else end
    mid_index = (end - start)//2 + start
    if start <= end:
        if l[mid_index] < aim:
            return find(l,aim,start =mid_index+1,end=end)
        elif l[mid_index] > aim:
            return find(l, aim, start=start, end=mid_index-1)
        else:
            return mid_index
    else:
        return '找不到这个值'

ret= find(l,44)
print(ret)

















2018年11月23日 星期五

python - 遞歸函數 遞迴函式

遞歸函數
.說明遞歸:  在函數中調用自身函數
     *最大遞歸次數默認是 997/998次
     *為python從內存角度出發作的限制
     *可使用 setrecursionlimit() 來修改限制上限,但會依照內存停止
   *如果遞歸次數太多,不是適合使用遞歸來解決問題
   *遞歸的缺點: 佔內存
   *遞歸的優點: 會讓代碼變簡單

.算法 --二分查找算法
.三級菜單  

*執行可以修改遞歸上限

import sys
sys.setrecursionlimit(900000000) #修改上限
n = 0
def story():
    global  n
    n += 1    print(n)
    story()

story()




遞歸舉例: 
趙雲  今年幾歲?                                 
趙雲  比 魏延 大兩歲   
魏延  今年幾歲??                            
魏延  比黃蓋   大兩歲
黃蓋  今年幾歲?                                 
黃蓋  比  劉備  大兩歲
劉備  今年幾歲??
劉備  40了              

趙雲  今年幾歲?          n = 1 age(1) = age(2)+2 = age(n+1) + 2
趙雲  比 魏延 大兩歲
魏延  今年幾歲??        n = 2 age(2) = age(3) + 2 = age(n+1) +2
魏延  比黃蓋   大兩歲
黃蓋  今年幾歲?          n = 3 age(3) = age(4) + 2 = age(n+1) +2
黃蓋  比  劉備  大兩歲
劉備  今年幾歲??
劉備  40了               n = 4 age(4) = 40
n = 4 age(4) = 40
n < 4 age(n) = age(n+1) +2
.寫成函數
def age(n) :
    if n == 4:
        return  40    elif n > 0 and n < 4 :
        return age(n+1) + 2print(age(1))
運行結果:
46
.拆解看
def age(1):
    if 1 == 4:
        return 40    elif 1 > 0 and 1 < 4:
        return 46
def age(2):
    if 2 == 4:
        return 40    elif 2 >0 and 2 < 4:
        age(3) + 2    None +2
def age(3):
    if 3 == 4:
        return 40    elif 3 >0 and 3 < 4:
        42
def age(4):
    if 4 == 4:
        return 40    elif n >0 and n < 4:















2018年11月22日 星期四

python - 習題 內置函數 map


#用map 來處理字符串列表,把列表中所有人都變成 貴賓,
#如王小民_貴賓#解題方式有兩種
#第一種name = ["王小民",'李小白','陳小心']
def func(item):
    return  item +'貴賓'   #ret 是迭代器ret = map(func,name)
for  i in ret :
    print(i)

#第二種 匿名函數
ret = map(lambda  item:item + '_貴賓',name )
print(list(ret))
執行結果:
王小民貴賓
李小白貴賓
陳小心貴賓
['王小民_貴賓', '李小白_貴賓', '陳小心_貴賓']

#用filter函數處理數字列表,將列表中所有的偶數篩選出來
#兩種方法name = [1,2,3,4,5,6,7,8,9]
def func(x):
    if x%2 == 0:
        return  True
ret = filter(func,name) #ret 是迭代器
print(list(ret))

#另外方法
ret = filter(lambda x: x% 2 == 0,name)
ret = filter(lambda x: True if x%2 == 0 else False,name)
print(list(ret))
執行結果:
[2, 4, 6, 8]
[2, 4, 6, 8]

#主要內容輸入特定數字顯示該行行數內容,每五行為一單位
#例如輸入1,顯示出1 2 3 4 5 6 輸入2 6 7 8 9 10 .....等
#運行程式,先將內容讀到記憶體中,用列表儲存
#創建一個叫egg的文件 內有20個行以上內容
with open('egg',encoding='utf-8') as f:
l = f.readlines() # readlines 可逐行讀取
page_num = int(input('請輸入頁數:'))
pages,mod = divmod(len(l),5)
#求有多少頁,有沒有剩餘的行數
# len 返回長度數量,divmod 可以A除以B (被除數,除數)
if mod :
#如果有剩餘的行數,那麼頁數加一
pages += 1 #一共有多少頁
if page_num > pages or page_num <= 0 :
#用戶輸入的頁數大於總數或者小於等於0    
print('輸入有誤')
elif page_num == pages and mod != 0 :
#如果用戶輸入的頁碼是最後一頁,且之前有過剩餘行數
for i in range(mod):
print(l[(page_num-1)*5 + i].strip())
#只輸出這一頁上剩餘的行
else :
for i in range(5):#正常情況,輸出5行
print(l[(page_num-1)*5 +i].strip())

執行結果:
請輸入頁數:1
1
2
3
4
5



#寫一個小字典
# name對應股票名子
# shares 對應多少股
# price對應股票的價格

portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},    
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},    
    {'name': 'FB', 'shares': 200, 'price': 21.09},    
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},    
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},    
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]

# .計算購買每支股票的總價ret = map(lambda  dic :{dic['name']:
                            round(dic['shares']*dic['price'],2)},portfolio)
print(list(ret))

# .用filter過濾出,單價大於100的股票有哪些
rett = filter(lambda dic:True if dic['price']>100 else False,portfolio)
print(list(rett))
# 另外方法rettt = filter(lambda  dic:dic['price']>100,portfolio)
print(list(rettt))
執行結果:
[{'IBM': 9110.0}, {'AAPL': 27161.0}, {'FB': 4218.0}, {'HPQ': 1111.25}, {'YHOO': 735.75}, {'ACME': 8673.75}]

[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}]
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}]


2018年11月18日 星期日

python - 生成器進階 關鍵字 send

生成器進階 -send 關鍵字
.send 獲取下一個值的效果和next 基本一致
.只在獲取下一個值得時候,給上一個yield 的位置傳遞一個數據
.使用send的注意事項
        1.第一次使用生成器的時候 是用next獲取下一個值(必須) 
        2.最後一個yield 不能接受外部的值
        3.一定要先給一個值


def  generator ():
    print(123)
    content = yield  1    print('========',content)
    print(456)
    arg =  yield  2    ''''''    yieldg1 = generator()
g2 = generator()
g1.__next__()
g2.__next__()
print('****',generator().__next__())
print('****',generator().__next__())


g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')    #sendprint('****',ret)

執行結果:
123
123
123
**** 1
123
**** 1
123
*** 1
======== hello
456
**** 2








2018年11月15日 星期四

python - 函數總結

函數總結:



*函數的定義以及調用:


               def  函數名(形參) :
                                  函數體
                                  return 返回值


*調用  函數名(實參)
     關於  形參 :  位置參數,*args, 默認參數(陷阱問題),**kwargs
      關於  實參:   按照位置傳、按照關鍵字傳

#默認參數 陷阱 :  函数中的参数默认值是一个可变的list, 函数体内修改了原来的默认值,而python会将修改后的值一直保留,并作为下次函数调用时的参数默认值

*返回值 : 沒有返回值、返回一個值、返回多個值
        返回值的接收方法:  沒有返回值  >>>不接收
        返回一個值  >>>用一個變量接收
        返回多個值 >>>用一個變量接收或是對應的數目變量接收

*閉包函數   在內部函數引用外部函數的變量
*裝飾器
        裝飾器的作用:  再不改變原來的函數的調用方式的情況下,在這個函數的前後添加新的                                       功能。
      
       完美的符合了一個開發原則  : 開放封閉原則
                  1.對擴展的是開放的
                  2.對修改的是封閉的


1.基礎的裝飾器

#基礎的裝飾器def   wrapper(func):
    def inner(*args,**kwargs):
        ''' 在函數被調用之前添加的代碼'''        ret = func(*args,**kwargs) #func 是被裝飾的函數 在這裡被調用        '''在函數被調用之後添加的代碼'''        return  ret
    return  input#使用 -- @wrapper
                    

2.完美的裝飾器
from functools  import wraps
#完美的裝飾器from functools import wraps
def   wrapper(func):
    def inner(*args,**kwargs):
        ''' 在函數被調用之前添加的代碼'''        ret = func(*args,**kwargs) #func 是被裝飾的函數 在這裡被調用        '''在函數被調用之後添加的代碼'''        return  ret
    return  input#使用 -- @wrapper 

3.帶參數的裝飾器
  .@wrapper  >>@warapper(argument) 
  .三層嵌套函數
  #三層嵌套裝飾器.帶參數裝飾器
def outer(形參):
        def   wrapper(func):
            def inner(*args,**kwargs):
                ''' 在函數被調用之前添加的代碼'''                ret = func(*args,**kwargs) #func 是被裝飾的函數 在這裡被調用                '''在函數被調用之後添加的代碼'''                return  ret
            return  input        return  wrapper
@outer(True)
def func():
    pass

4.多個裝飾器裝飾一個函數
俄羅斯娃娃
def wrapper1(func):
            @wraps(func)
            def inner(*args,**kwargs):
                print('before 1')
                print('******')
                ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用                '''在函数被调用之后添加的代码'''                return ret
    def wrapper2(func):
        @wraps(func)
        def inner(*args,**kwargs):
            print('before 2')
            ret = func(*args,**kwargs)   # func是被装饰的函数 在这里被调用            '''在函数被调用之后添加的代码'''            return ret
      @wrapper1      @wrapper2      def func():
          print('111')






2018年11月14日 星期三

python - 帶參數的裝飾器

#帶參數的裝飾器#500個函數import  time
FLAGE  =  Falsedef timmer_out(flag):
    def timmer(func):
        def inner(*args,**kwargs) :
            if flag:
                start =  time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end - start)
                return   ret
            else:
                ret = func(*args,**kwargs)
                return  ret
        return  inner
    return  timmer
#timmer =  timmer out(FLAGE)@timmer_out (FLAGE)  # wahaha =  timmer(wahaha)def wahaha():
    time.sleep(0.1)
    print("wawawahahahaha")

@timmer_out(FLAGE)
def erguotou():
    time.sleep(0.1)
    print("ererereyoyoyoyo")

wahaha()
erguotou()

#多個裝飾器裝飾一個函數def wrapper1(func):
    def inner1():
        print('wrapper1 ,before func')
        ret = func()
        print('wrapper1 ,after func')
        return  ret
    return  inner1
def wrapper2(func):
    def inner2():
        print('wrapper2 ,before func')
        ret = func()
        print('wrapper2 ,after func')
        return  ret
    return  inner2

def wrapper9(func):
    def inner3():
        print('wrapper3 ,before func')
        ret = func()
        print('wrapper3 ,after func')
        print('test 1')
        return  ret
    return  inner3
@wrapper9@wrapper2@wrapper1
def f():
    print('in f')
    return  '哈哈哈'
print(f())
執行結果:
wrapper3 ,before func
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
wrapper3 ,after func
test 1
哈哈哈







2018年11月13日 星期二

python -day12 作業 -裝飾器

1.編寫裝飾器,為多個函數加上認證的功能(用戶的帳號密碼來源於文件)
要求登入成功一次,後續的函數都無需要在輸入用戶名和密碼

FLAG = Falsedef login(func):
    def inner(*args,**kwargs):
        global FLAG
        '''登入程式'''        if FLAG:
            ret = func(*args,**kwargs) #func是被裝飾的函數            return  ret
        else:
            username = input('username  : ')
            password = input('password  : ')
            if username  == 'boss_gold'  and password == '22222':
                FLAG = True                ret =  func(*args,**kwargs)  #func是被裝飾的函數                return   ret
            else:
                print('登入失敗')
    return  inner

@logindef shoplist_add() :
    print('增加的一件物品')

@logindef  shoplist_del() :
    print('刪除一件物品')

shoplist_add()
shoplist_del()
執行結果:
username  : boss_gold
password  : 22222
增加的一件物品
刪除一件物品



2.編寫裝飾器,為多個函數加上紀錄調用功能,要求每次調用函數都將
被調用的函數名稱寫入文件

def  log(func) :
    def inner(*args,**kwargs):
        with open('log','a',encoding='utf-8') as f :
            f.write(func.__name__+'\n')
        ret =  func(*args,**kwargs)
        return  ret
    return  inner


@logdef shoplist_add() :
    print('增加一件商品')

@logdef shoplist_del () :
    print('刪除一件物品')


shoplist_add ()

運行結果:
增加一件商品

3.編寫下載網頁內容的函數,要求功能是:用戶傳人一個url,函數返回下載頁面的結果
為題目1編寫裝飾器,實現緩存網頁內容的功能:


具體內容: 實現下載的頁面存放於文件中,如果文件內有值(文件大小不為0),
就優先從文件中讀取網頁內容,否則就去下載,然後存到文件中

import  os
from urllib .request import  urlopen
def cache(func):
    def inner(*args,**kwargs):
        if  os.path.getsize('web_cache'):
            with open('web_cache','rb') as f:
                return  f.read()
        ret = func(*args,**kwargs) #grt()        with open('web_cache','wb') as f:
            f.write(b'***********'+ret)
        return  ret
    return  inner

@cachedef get(url):
    code = urlopen(url).read()
    return  code


ret = get('http://www.baidu.com')
print(ret)
ret = get('http://www.baidu.com')
print(ret)
ret = get('http://www.baidu.com')
print(ret)
執行結果:
#網頁代碼


















python- 生成器、迭代器、yield、監聽文件輸入

迭代器:
雙下(雙下滑線)方法: 很少直接調用的方法。一般情況下,是通過其他語法觸發的
可迭代的規則--可迭代協議 含有( __iter__的方法( '__iter__' dir數據)
可迭代的一定可以被for循環。
迭代器一定可迭代,可迭代的通過調用iter()方法就能得到一個迭代器
迭代器特點:
              1.很方便使用,且只能取得所有的數據取一次
              2.節省內存空間

生成器:
.生成器函數--就是我們自己寫的函數
生成器的本質就是迭代器
生成器的表現形式
    1.生成器函數
    2.生成器表達式
生成器函數:
    1.含有yield 關鍵字的函數就是生成器函數
    2.特點:
                 .調用函數的之後函數不執行,返回一個生成器
                 .每次調用next方法的時候可以取得一個值
                 .直到取完最後一個,在執行next會報錯

生成器實現:有一個文件,從文件裡分段讀取內容
readline 取整行的方法
read(10) 取X數量的方法
在讀出來的內容前面加上一個 "****" ,再返回給調用者



執行結果:
哇哈哈0
哇哈哈1
哇哈哈2
哇哈哈3
哇哈哈4
哇哈哈5
哇哈哈6
哇哈哈7
哇哈哈8
哇哈哈9
哇哈哈10
哇哈哈11
哇哈哈12
哇哈哈13
哇哈哈14
哇哈哈15
哇哈哈16
哇哈哈17
哇哈哈18
哇哈哈19



從生成器中取值的幾個方法
                   next
                   fot
                   數據類型的強制轉換:  佔用內存





1.使用return  方法
#生成器函數def  generator():
    print(1)
    return  'a'
ret  =  generator()
print(ret)

執行結果:
1

a



.yield關鍵字

.yield的函數不再是一個普通的函數,而是一個生成器generator,可用於迭代。
.類似returm  的關鍵字,迭代時遇到就會返回yieldc右邊(後方)的值。在執行下次迭代時會從上一次遇yieldc的後方程序(下一行)開始執行。
.yield的函數可以用在for循環中以及函數的參數上,只要這個函數允許迭代參數,array.extend函數,它的原型是array.extend(iterable)。
.yield不可以跟returm 共用,且需要寫在函數內


使用yield
#生成器函數def  generator():
    print(1)
    yield"a"#生成器函數:執行之後會得到一個生成器作為返回值
ret  =  generator()
print(ret)
print(ret.__next__())



.當執行到yield 時會停止然後傳回值,如果再次執行會再從上次的地方跳行執行
def   gemerator():
    print(1)
    yield "a"    print(2)
    yield "b"g  = gemerator()
ret=g.__next__()
print(ret)
ret=g.__next__()
print(ret)

執行結果:
1
a
2
b



.也可以使用for來接收yield的值
def   gemerator():
    print(1)
    yield "a"    print(2)
    yield "b"g  = gemerator()
for i  in g:
    print(i)
# ret=g.__next__()# print(ret)# ret=g.__next__()# print(ret)
執行結果:
1
a
2
b



.可以快速的處裡大量數據 

def  eess():
    for  i  in range(2000000000):
        yield "執行第%s"%i

g =  eess()
for i  in g:
    print(i)



.限制生成數量,如果再次執行可以在往下接取
def  eess():
    for  i  in range(2000000000):
        yield "執行第%s"%i

g =  eess()
count = 0for i  in g:
    count += 1    print(i)
    if count >50:
        break
g =  eess()
 
for i  in g:
    count += 1    print(i)
    if count >100:
        break

.列表是一個可迭代對象,如果要讓使用迭代要轉換成迭代器

l  =  [1,2,3,4,5]
for  i  in l:
    print(i)
    if i == 2:
        breakfor i  in l:
    print(i)
執行結果:
1
2
1
2
3
4

5


.生成器的引用互不相同,可看到下面g跟g111是不同的生成器
def  eecco():
    for i  in range(100):
        yield  "執行程序%s" %i
g =  eecco()
g111 = eecco()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print('另一個',g111.__next__())
print('另一個',g111.__next__())

.監聽file文件的內容並且打印出來

f  =  open('file',encoding="utf-8")
while True:
    line  = f.readline()
    if line:


將原本監聽功能改成函數

def tail(foodde):
    f  =  open(foodde,encoding="utf-8")
    while True:
        line  = f.readline()
        if line:
            print(line.strip())

tail('file')

.將監聽器改成生成器特性,並增加可以過濾文字功能

def tail(foodde):
    f  =  open(foodde,encoding="utf-8")
    while True:
        line  = f.readline()
        if line.strip():
            yield   line.strip()

g = tail('file')
for i in g:
    if "python" in i:
        print("****",i)
執行結果:
**** python

**** python.55









2018年11月11日 星期日

python- 裝飾器進階

裝飾器進階
.functools .wraps
.帶參的裝飾器
.多個裝飾器裝飾同一個函數

def  wrapper(func):
    def inner(*args,**kwargs):
        print('在被裝飾的函數執行之前做的事情')
        ret  =   func(*args,**kwargs)
        print('在被裝飾後的函數執行之後做的事情')
        return  ret
    return  inner

@wrapper #holdav  - wrapper(holiday)def holiday(day):
    print("全體放假%s天"%day)
    return  '好開心'
ret = holiday(3)
print(ret)
執行結果:
在被裝飾的函數執行之前做的事情
全體放假3天
在被裝飾後的函數執行之後做的事情

好開心







python- 開放封閉原則和裝飾器的作用(python重要原則)

開放封閉原則: 
    不修改函數的調用方式(名稱或是方法),但是想在原本的函數前後添加功能。
    timmer 就是一個裝飾器函數,只是對一個函數有一些裝飾作用。(參考裝飾器篇)

.開放:  對擴展是開放的,可以調用或是增加。
.封閉:  對修改是封閉的,無法對原本的代碼進行修改。

2018年11月10日 星期六

python - 裝飾器、語法糖、調用函數


裝飾器

.functools. wraps
.帶參數的裝飾器
.多個裝飾器同一個函數 

裝飾器本質: 
1.為函數,功能是為其他函數添加附加功能。
2.開發原則:  開發封閉原則
3.裝飾器的作用:  在不改變原函數的的調用方式情況下,在函數的前後添加功能,不修改被修飾函數的源代碼
4.裝飾器的本質:  閉包含數
5.開放封閉原則


裝飾器的組成:
裝飾器  =  高階函數  +  函數嵌套 + 閉包



 主要目的: 
寫一個計算時間的程序來計算程序運行的時間,然後在不破壞原本程序原碼的情況下,增加裝飾器讓他可以被調用,之後要再擴展都可以不用改動原本代碼。


1.寫一個簡單程序 來計算程序運行時間

import  time

def  func():
    start = time.time()
    print("要運行程序")
    time.sleep(0.01)#等待時間    end =  time.time()
    print(end - start)

func()

運行結果: 
要運行程序

0.010040044784545898






2.加入一個可以調用的函數,這樣可以方便給其他人調用,不管誰
只要想使用這功能就可以調用,但是這樣會修改到原本調用得名稱,
原本調用的是func(),但這邊被修改了!所以要使用裝飾器把這功能
加入只要使用func()就可以增加其他函數功能。
import  time

def timmer(f):
    start = time.time()
    f()
    end = time.time()
    print(end - start)



def  func():
    print("要運行程序")
    time.sleep(0.01)#等待時間
timmer(func)
運行結果: 
要運行程序
0.010941743850708008




3.使用閉包來修改,讓程序只要使用func()也可以調用函數
import  time

def timmer(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print(end - start)
    return  inner

def  func():
    print("要運行程序")
    time.sleep(0.01)#等待時間
func =  timmer(func)
func()
運行結果: 
要運行程序
0.01000070571899414

執行步驟:
語法糖
import  time

def timmer(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print(end - start)
    return  inner

@timmer            #語法糖 @裝飾器函數名def  func():       #被裝飾的函數    print("要運行程序")
    time.sleep(0.01)#等待時間
#func =  timmer(func)  因語法糖屏蔽func()
執行結果:
要運行程序
0.010973453521728516



.調用得數據為空


import  time

def   wrapper(f): #裝飾器函數,f是被裝飾的函數    def inner(*args,**kwargs):
        '''再被裝飾函數之前要做的事'''        ret = f(*args,**kwargs)
        '''在被裝飾函數之後要做的事'''        return ret
    return   inner

@wrapper   #語法糖@裝飾器函數名def func(a,b):   #被裝飾的函數    time.sleep(0.01)
    print('被調用的函數',a,b)
    return  '增加數據'
def wrapper():
    def inner():
        pass    return  inner

.調用數據
def wrapper(func): #abcce    def inner(*args,**kwargs):
        ret = func(*args,**kwargs)   #被裝飾的函數        return  ret
    return  inner

@wrapper   #abcce = wrapper(abcce)def abcce():
    print(1232)
ret = abcce() #inner

執行結果:
1232
.