第三篇.六、python基礎補充

'''
不可變:數字,字符串,元組
可變:列表,字典

原子:數字,字符串
容器:列表,元組,字典

直接訪問:數字
順序:字符串,列表,元組
映射訪問:字典

'''

#一一對應
a,b,c,d,e='hello'
print(e,d)

#少一個報錯
# a,b,c='hello'

#*號的使用
a,*_,e='hello'
print(a,e)

#列表中的元素解壓也是一一對應的關係
data=['mac',10000,[2016,10,12]]
name,price,date=data
print(name,price,date)

#截取子元素
name,price,[year,month,day]=data
print(name,price,year,month,day)

#無用的元素用_代替
data=['mac',10000,[2016,10,12]]
_,price,_=data
print(price)

#頭截取,尾截取
record=['lhf','male',18,'12345@qq.com','1861131211']
*_,phone=record
name,*_=record
print(phone)
print(name)

#解壓可迭代對象賦值給多個值
#一個八個月的業績與前七個月的平均值比較

sales_record=[11,12,3,7,9,6,3,5]
*head,tail=sales_record
print(head,tail)
print(sum(head)/len(head))
if tail > sum(head)/len(head):
    print('第八個月業績高於前七個月平均值')
elif tail == sum(head)/len(head):
    print('第八個月業績等於前七個月平均值')
else:
    print('第八個月業績小於前七個月平均值')



#解壓元素在函數中的應用

records=[
    ('say_hi','hello'),
    ('calculate',10,20,30,40),
    ('dic_handle','name','lhf')
]

def say_hi(msg):
    print(msg)

def calculate(l):
    res=0
    for i in l:
        res+=i
    print(res)

def dic_handle(l):
    key,val=l
    dic={key:val}
    print(dic)

for func,*args in records:
    if func == 'say_hi':
        say_hi(args)
    elif func == 'calculate':
        calculate(args)
    elif func == 'dic_handle':
        dic_handle(args)

#linux系統中用戶記錄
record='root:x:0:0:super user:/root:/bin/bash'
*head,home_dir,_=record.split(':')
print('家目錄',home_dir)
解壓序列賦值給多個變量
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
from collections import deque

# #實現隊列,不指定大小則無限添加
# d=deque(maxlen=3)
# d.append(1)
# d.append(2)
# d.append(3)
# print(d)
# d.append(4)
# print(d)
# d.appendleft(5)
# print(d)
# print(d.pop())
# print(d.popleft())

def search(file,pattern,max_len=5):
    pre_lines=deque(maxlen=max_len)
    for line in file:
        if pattern in line:
            yield pre_lines,line
        pre_lines.append(line)

if __name__ == '__main__':
    with open('測試文件') as file:
        for pre_l,line in search(file,'Exchange'):
            print('-'*60)
            for i in pre_l:
                print(i)
            print('匹配行----->',line)
保留最後n個元素
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

import heapq

nums=[1,2,3,-10,100,30,200,21,9,7]
print(heapq.nlargest(3,nums))
print(heapq.nsmallest(3,nums))



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

cheap=heapq.nsmallest(3,portfolio,key=lambda x:x['price'])
print(cheap)

'''
若是你想在一個集合中查找最小或最大的N個元素,
而且N小於集合元素數量, 那麼這些函數提供了很好的性能。
由於在底層實現裏面,首先會先將集合數據進行堆
排序後放入一個列表中
'''

heapq.heapify(nums)
print(nums)
'''
堆數據結構最重要的特徵是heap[0]永遠是最小的元素。
而且剩餘的元素能夠很 容易的經過調用heap.heappop()方法獲得,
該方法會先將第一個元素彈出來,而後 用下一個最小的元素來取代被彈出元素
(這種操做時間複雜度僅僅是O(log N),N是堆大小。)好比,若是想要查找最小的3個元素,
你能夠這樣作:
'''
print(heapq.heappop(nums))
print(heapq.heappop(nums))
print(heapq.heappop(nums))

'''
nlarges(),nsmallest():當要查找的元素個數相對較小時使用
min(),max():就是要找惟一一個最大的或者最小的值時使用
sort[items][n:m]:當要查找的元素個數相接近items長度時使用
'''
查找最大或最小的n個元素
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import heapq

class PriotryQueue:
    def __init__(self):
        self._queue=[]
        self._index=0

    def push(self,item,priotry):
        heapq.heappush(self._queue,(-priotry,self._index,item))
        self._index+=1

    def pop(self):
        return heapq.heappop(self._queue)[-1]

class Item:
    def __init__(self,name):
        self.name=name

    def __str__(self):
        return self.name

    def __repr__(self):
        # return self.name
        return 'Item({!r})'.format(self.name)
q=PriotryQueue()
q.push(Item('鎮長'),1)
q.push(Item('省長'),4)
q.push(Item('主席'),5)
q.push(Item('市長'),3)
q.push(Item('縣長'),2)

print(q._queue)

print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())
print(q.pop())
基於heapq實現優先級隊列
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

'''
一個字典就是一個鍵對應一個單值的映射。
若是你想要一個鍵映射多個值,那麼你就需
要將這多個值放到另外的容器中,好比列表
或者集合裏面。好比,你能夠像下面 這樣構造這樣的字典:
'''

people={
    'name':['alex','李傑'],
    'hobby':['play','coding']
}

project={
    'company':{'IBM':'CTO','Lenovo':'CEO','baidu':'COO','Alibaba':'UFO'},
    'applicant':['小白','lhf','武藤蘭']
}

'''
選擇使用列表仍是集合取決於你的實際需求。
若是你想保持元素的插入順序就應該使用列表,
若是想去掉重複元素就使用集合(而且不關心元素的順序問題)。
你能夠很方便的使用collections模塊中的defaultdict來構造這樣的字典。             的一個特徵是它會自動初始化每一個     剛開始對應的值,因此你只須要 關注添加元素操做了。好比:
'''
from collections import defaultdict
d=defaultdict(list)
d['teacher'].append('alex')
d['teacher'].append('wupeiqi')
d['teacher'].append('wuqiqi')
d['boss'].append('oldboy')
d['boss'].append('alex')

d_set=defaultdict(set)
d_set['a'].add(1)
d_set['a'].add(2)
d_set['a'].add(3)

print(d,d_set)

#setdefault
d={}

d.setdefault('a',[]).append(1)
d.setdefault('a',[]).append(2)
d.setdefault('a',[]).append(2)
print(d)

#本身實現一個一鍵多值字典
l=[
    ('teacher','alex'),
    ('teacher','lhf'),
    ('teacher','papa'),
    ('boss','alex'),
    ('boss','wupeiqi'),
]
d={}
for k,v in l:
    if k not in d:
       d[k]=[]
    d[k].append(v)
print(d)

#用defaultdict實現,更優雅
d=defaultdict(list)
for k,v in l:
    d[k].append(v)

print(d)
實現一個multidict
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

from collections import OrderedDict
d=OrderedDict()
d['dream1']='先掙他媽一個億'
d['dream2']='而後周遊全世界'
d['dream3']='再娶他媽七八個媳婦'
d['dream4']='洗洗臉,而後夢就醒了'

for key in d:
    print(key,d[key])

# import json
# print(json.dumps(d))

'''
OrderedDict內部維護着一個根據鍵插入順序排序的雙向鏈表每次當一個新的元素
插入進來的時候,它會被放到鏈表的尾部對於一個已經存在的鍵的重複賦值不會改變
鍵的順序。須要注意的是,一個OrderedDict的大小是一個普通字典的兩倍,由於它
內部維 護着另一個鏈表。因此若是你要構建一個須要大量OrderedDict實例的數
據結構的時候,那麼你就得仔細 權衡一下是否使用OrderedDict帶來的好處要大過
額外內存消耗的影響。
'''
建立有序字典
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
prices={
    'ACME':45.23,
    'AAPL':612.78,
    'IBM':205.55,
    'HPQ':37.20,
    'FB':10.75
}

#zip()建立的是隻能訪問一次的迭代器,下面的max()會報錯
# prices_and_names=zip(prices.values(),prices.keys())
# min_price=min(prices_and_names)
# max_price=max(prices_and_names)

#單純的min(prices)是按照key來取值


min_price=min(zip(prices.values(),prices.keys()))
max_price=max(zip(prices.values(),prices.keys()))

print(min_price)
print(max_price)


print(min(prices,key=lambda k:prices[k]))
print(max(prices,key=lambda k:prices[k]))

'''
須要注意的是在計算操做中使用到了(值,鍵)對。當多個實體
擁有相同的值的時 候,鍵會決定返回結果。好比,在執行min()
和max()操做的時候,若是恰巧最小或 最大值有重複的,那麼擁
有最小或最大鍵的實體會返回
'''
prices={'A':45.23,'Z':45.23}

print(min(zip(prices.values(),prices.keys())))
字典的運算
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
a={
    'x':1,
    'y':2,
    'z':3,
}

b={
    'w':1,
    'x':2,
    'y':3,
}

print(a.keys() & b.keys())
print(a.keys() - b.keys())
print(a.items() - b.keys())


#生成一個新的字典,去掉某些key

c={key:a[key] for key in a.keys() - {'z','w'}}
print(c)
查找倆字典的相同點
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

a=[1,5,2,1,9,1,5,10]

#若是想簡單去重,能夠使用set,可是set是無序的
# print(set(a))

#若是序列的值都是hashable類型,那麼能夠簡單利用集合或者生成器來解決這個問題
def dedupe(items):
    seen=set()
    for i in items:
        if i not in seen:
            yield i
            seen.add(i)
print(list(dedupe(a)))


#若是序列元素是不可hashable類型
a=[
    {'name':'alex','age':18},
    {'name':'alex','age':100},
    {'name':'alex','age':100},
    {'name':'lhf','age':18},

]

def dedupe(items,key=None):
    seen=set()
    for i in items:
        k=i if not key else key(i)
        if k not in seen:
            yield i
            seen.add(k)
print(list(dedupe(a,key=lambda k:(k['name'],k['age']))))

#去除文件中相同的內容用第一種方法便可
去除序列中重複的值且保持順序
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

#普通切片,一堆硬編碼
record='蒼井空'
record1='abcde'
print(record[1:3])
print(record1[1:3])

#命名切片,減小硬編碼
record='蒼井空 18621452550 沙河匯德商廈'
phone=slice(4,15)
addr=slice(16,21)
print(record[phone])
print(record[addr])

'''
通常來說,代碼中若是出現大量的硬編碼下標值會使
得可讀性和可維護性大大降 低。好比,若是你回過來
看看一年前你寫的代碼,你會摸着腦殼想那時候本身到
底想 幹嗎啊。這裏的解決方案是一個很簡單的方法讓
你更加清晰的表達代碼到底要作什麼。內置的slice()
函數建立了一個切片對象,能夠被用在任何切片容許使用
的地方。
'''

s=slice(5,50,2)
print(s.start)
print(s.stop)
print(s.step)
命名切片
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
from collections import Counter
words=['if', 'you', 'were', 'a',
       'you,I', 'would', 'never','if',
       'would', 'if']
# d={}
# for word in words:
#     if word not in d:
#         d[word]=1
#     else:
#         d[word]+=1
# print(d)

word_counts=Counter(words)
# print(word_counts)

#統計出現頻率最高的3個單詞
print(word_counts.most_common(2))

#能夠像字典同樣取值
print(word_counts['if'])

#新增單詞
more_words=['if','if']
for word in more_words:
    word_counts[word]+=1

print(word_counts)
#或者直接使用
word_counts.update(more_words)
print(word_counts)


#counter實例能夠進行數學運算

a=Counter(words)
b=Counter(more_words)
print(a)
print(b)
print(a-b)
print(b-a)
print(a+b)
Counter統計出現次數最多的元素
文件conf.txt內容
global
        log 127.0.0.1 local2
        daemon
        maxconn 256
        log 127.0.0.1 local2 info
defaults
        log global
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
        option  dontlognull

listen stats :8888
        stats enable
        stats uri       /admin
        stats auth      admin:1234

frontend oldboy.org
        bind 0.0.0.0:80
        option httplog
        option httpclose
        option  forwardfor
        log global
        acl www hdr_reg(host) -i www.oldboy.org
        use_backend www.oldboy.org if www

backend www.oldboy.org
        server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000

原配置文件


deque_test.py內容

from collections import deque
import re

def conf_dic(f):
    dic={}
    for line in f:
        if re.match('[a-zA-Z]',line):
            key=line
        elif re.match('^ ',line):
            dic.setdefault(key,[]).append(line)

    return dic



if __name__ == '__main__':
    with open('conf.txt',encoding='utf-8') as f:
        dic=conf_dic(f)

    for i in dic:
        print('%s' %i,end='')
        for line in dic[i]:
            print(line,end='')
        print('-'*20)
讀取配置文件組成字典
#_*_coding:utf-8_*_
__author__ = 'Alex Li'
from operator import itemgetter

rows=[
    {'fname':'Brian1','lname':'Jones1','uid':1003},
    {'fname':'Brian2','lname':'Jones2','uid':1002},
    {'fname':'Brian3','lname':'Jones3','uid':1001},
    {'fname':'Brian4','lname':'Jones4','uid':1004},
]
# rows_by_uid=sorted(rows,key=lambda rows:rows['uid'])
# for i in rows_by_uid:
#     print(i)
#
#
#
# rows_by_uid=sorted(rows,key=itemgetter('uid'))
# for i in rows_by_uid:
#     print(i)


rows_by_lfname=sorted(rows,key=itemgetter('lname','fname'))
print(rows_by_lfname)
for i in rows_by_lfname:
    print(i)
字典經過關鍵字排序
#_*_coding:utf-8_*_
__author__ = 'Alex Li'

#要生成列表
l=[]
for i in range(6):
   i*=2
   l.append(i)
print(l)



y=[i*2 for i in range(6)]
print(y)


def func(n):
    return n+10
z=[func(i) for i in range(6)]
print(z)

l=[1,2,3,-1,-10,4,5]
#過濾掉負數
l_new=[i for i in l if i >= 0]
print(l_new)
列表解析
#_*_coding:utf-8_*_
__author__ = 'Alex Li'


#生成器,取一次生成一個值,只能next不能回退,由於只有一個

l=[i for i in range(10000000)] #機器卡死
g=(i for i in range(1000000)) #一秒生成
g.__next__()
#next到最後報異常


def fib(n1,n2,count=0):
    if count > 10:return
    if count == 0:
        print('',n1,end='')

    x=n2
    n2=(n1+n2)
    n1=x
    print(' ',n2,end='')
    count+=1
    fib(n1,n2,count)



#
# 0 1 1 2 3 5 8 13 21

# fib(0,1)
#
def fib2(max=10):
    n,a,b=0,0,1
    while n < max:
        # x=b
        # b=b+a
        # a=x
        yield b
        a,b=b,a+b
        # print(' ',b,end='')

        n+=1
    return 'done'

x=fib2()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()
x.__next__()

# while True:
#     try:
#         print(x.__next__())
#     except Exception as e:
#         print(e)
#         break
生成器
#_*_coding:utf-8_*_
__author__ = 'Alex Li'
import time

def consumer(name):
    print('[%s]準備吃包子啦' %name)
    while True:
        baozi=yield

        print('包子[%s]來了,被[%s]吃了' %(baozi,name))


# c=consumer('alex')
# c.__next__()
# c.send('韭菜餡的')


def producter():
    c1=consumer('alex')
    c2=consumer('wupeiqi')
    c1.__next__()
    c2.__next__()
    print('開始作包子啦')
    for i in range(10):
        time.sleep(1)
        c1.send(i)
        c2.send(i)

producter()


f=open('a.txt')
f.__next__()
生成器並行運算
#_*_coding:utf-8_*_
__author__ = 'Alex Li'
name='lhf'
passwd='123'

def auth(auth_type):
    def inner_auth(func):
        def _wrapper(*args,**kwargs):
            username=input('username: ')
            password=input('passwd: ')
            if auth_type == 'local':
                if username ==  name and password ==passwd:
                    print('user login successfull')
                    res=func(*args,**kwargs)

                else:
                    exit('log err')
            elif auth_type == 'ldap':
                print('搞毛線ldap,誰特麼會')

        return _wrapper
    return inner_auth


def index():
    print('welcome to index page')

@auth(auth_type='local')
def home():
    print("welcome to home page")

@auth(auth_type='ldap')
def bbs():
    print('welcome to bbs page')

index()
home()
bbs()
帶參數裝飾器
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
prices={
    'ACME':45.23,
    'AAPL':612.78,
    'IBM':205.55,
    'HPQ':37.20,
    'FB':10.75
}
prices_new={key:val for key,val in prices.items() if val > 200}
print(prices_new)
從字典中提取子集
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
from collections import namedtuple
#商品,購買個數,單價
records=[
    ('mac',2,20000),
    ('lenovo',1,3000),
    ('apple',0,10),
    ('tesla',10,1000000)
]
'''
命名元組的一個主要用途是將你的代碼從下標操做中解脫出來。
所以,若是你從數 據庫調用中返回了一個很大的元組列表,通
過下標去操做其中的元素,當你在表中添 加了新的列的時候你
的代碼可能就會出錯了。可是若是你使用了命名元組,那麼就不
會有這樣的顧慮。
爲了說明清楚,下面是使用普通元組的代碼:
'''
cost=0.0
for rec in records:
    cost+=rec[1]*rec[2]
    print('商品:%s 購買個數:%s,總價格爲:%s' %(rec[0],rec[1],cost))


#使用命名元祖後
sk=namedtuple('Stock',['name','count','price'])
for rec in records:
    s=sk(*rec)
    print(s.count*s.price)

p=namedtuple('People',['name','gender','age'])
l=['alex','femal',18]
p1=p(*l)
print(p1)
print(p1.name)
print(p1.age)
print(p1.gender)

'''
命名元組另外一個用途就是做爲字典的替代,
由於字典存儲須要更多的內存空間。若是
你須要構建一個很是大的包含字典的數據結構,
那麼使用命名元組會更加高效。但 是須要注意的是,
不像字典那樣,一個命名元組是不可更改的。好比:
'''
p=namedtuple('People',['name','gender','age'])
l=['alex','femal',18]
p1=p(*l)
print(p1.name)
# p1.name='sb'#報錯,不可修改
p1=p1._replace(name='sb')#須要從新賦值給p1
print(p1.name)

#能夠新建一個函數,彌補必須使用_replace才能修改元素的缺點
p=namedtuple('People',['name','gender','age'])
p1=p('','',None)
def dict_to_stock(s):
    return p1._replace(**s)

print(dict_to_stock({'name':'alex','gender':'f','age':18}))
print(dict_to_stock({'name':'sb','gender':'f','age':18}))
nametuple命名元組
相關文章
相關標籤/搜索