長期置頂:
基礎教程: http://www.cnblogs.com/dahu-daqing/p/6629577.html
基礎教程: http://www.cnblogs.com/linhaifeng/p/7278389.html
爬蟲教程: http://www.cnblogs.com/linhaifeng/p/8241221.html
2018-02-07
socket
- https://www.cnblogs.com/alex3714/articles/5830365.html
- socket.SOCK_RAW 可用于 DDoS 攻擊
簡單 socket 例子(需要先啟動服務端)
- 客戶端
# Author:Freeman
import socket
client = socket.socket() # 聲明 socket 類型,同時生成socket連接對象,參數沒填,但是有默認參數
client.connect(("localhost", 6969))
client.send(b"Hello World!") #py3 不再允許字符串,需要 bytes 類型,bytes類型只能接受ASCII碼,因此這里如果想要輸入漢字:
# client.send("你好,世界!".encode("utf-8")) # 接受時需要 decode 解碼為 Unicode
data = client.recv(1024) # 最多接收1024個字節
print("recv:", data)
client.close()
- 服務端
# Author:Freeman
import socket
server = socket.socket()
server.bind(("localhost", 6969)) # 綁定要監聽的端口
server.listen() # 監聽
print("準備接收信息")
conn, addr = server.accept() # 服務端需要等信息傳進來
print(conn)
# conn:就是客戶端連過來,而在服務器端為其生成的一個實例
# <socket.socket fd=484, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969)
print(addr) # IP + 隨機端口
print("接收信息")
data = conn.recv(1024)
print("recv:", data)
conn.send(data.upper())
server.close()
- 實現類似接打電話的過程,A與B通話,這時C給A打來電話時先等待,等到A與B斷開之后再接入C
- 操作過程:
1.先啟動服務端
2.啟動客戶端,并在客戶端輸入文字:"客戶端1"
3.再啟動客戶端,在新客戶端輸入文字:“客戶端2”
4.斷開客戶端1(注意,不是紅色方塊,是下面的紅叉),查看 server 結果
# 服務端
import socket
server = socket.socket()
server.bind(("localhost", 6969)) # 綁定要監聽的端口
server.listen() # 監聽
print("準備接收信息")
while True:
conn, addr = server.accept() # 服務端需要等信息傳進來
while True:
data = conn.recv(1024)
if not data:
print("客戶端斷開")
break
print("recv:", data.decode())
conn.send(data.upper()) # upper() 轉大寫.將收到的數據轉換為大寫發送回客戶端
server.close()
# 客戶端
import socket
client = socket.socket() # 聲明 socket 類型,同時生成socket連接對象
client.connect(("localhost", 6969))
while True:
msg = input(">>:").strip()
# client.send(b"Hello World!")
client.send(msg.encode("utf-8"))
data = client.recv(1024) # 接收1024個字節
print("recv:", data.decode())
client.close()
2018-02-06
# Author:Gatling
class Person(object):
# hahahaha
'''描述信息'''
def __init__(self, name):
self.name = name
# lalalala
print(Person.__doc__) # 描述信息
-
__new__
是 用來調用__init__
反射
異常處理
2018-02-05
靜態方法
- @staticmethod:這玩意也是個裝飾器,必須寫在類中的函數,除此之外與類沒什么關系,定義時有什么參數就得傳什么參數,跟函數一樣。在靜態方法里訪問不了類或實例中的任何屬性和方法
類方法
- @classmethod:只能調用 class 自身的變量,無法訪問實例變量。例如一個類自身有name 屬性,它的實例也具有 name 屬性,通常是先調用實例的name,但如果想強行調用 類 的 name 就可以用到了
屬性方法
- @property:把一個方法變成靜態屬性,調用時不能再添加括號
# Author:Gatling
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.__food = None
@property
def eat(self):
print("%s is %s years old,eating %s" % (self.name, self.age, self.__food))
@eat.setter # 傳參數
def eat(self, food):
print("set to food:", food)
self.__food = food
@eat.deleter
def eat(self):
del self.__food
print("已刪除")
Freeman = Person("Freeman", 18)
Freeman.eat
Freeman.eat = "包子"
Freeman.eat
del Freeman.eat
Freeman.eat
# Freeman is 18 years old,eating None
# set to food: 包子
# Freeman is 18 years old,eating 包子
# 已刪除
# Traceback (most recent call last):
# File "D:/ForPython/爬蟲.py", line 29, in <module>
# Freeman.eat
# File "D:/ForPython/爬蟲.py", line 10, in eat
# print("%s is %s years old,eating %s" % (self.name, self.age, self.__food))
# AttributeError: 'Person' object has no attribute '_Person__food'
2018-02-04
面向對象
# 假設創建一個CS游戲:
# 有角色
# 射擊
# 中槍
# 買槍
class Role(object):
# 構造函數中的每個屬性在新實例化一個對象的時候都會創建一份
# 而方法只在 Role 中,不會隨著新創建實例化對象而創建,每次調用的時候實際上是訪問 Role 這個 class 中的方法
def __init__(self, name, role, weapon, life_value=100, money=15000):
# 構造函數
# 在實例化時做一些類的初始化的工作
# self 用于在實例化時傳入'實例變量(靜態屬性)'(就是后面的 r1,r2)
# self 的作用域就是 實例變量本身
# Role(r1,..,..,..) 通過這樣的方式告訴 Role 它的'實例變量'是 r1
self.name = name
self.role = role
self.weapon = weapon
# self.life_value = life_value
self.__life_value = life_value # 私有屬性
self.money = money
def __del__(self):
# 析構函數:在實例釋放或銷毀的時候自動執行的
# 通常用于做一些收尾工作,如關閉數據庫連接或之前打開的臨時文件
print("%s 觸發析構函數" % self.name)
def show_status(self):
# 用于訪問私有屬性的函數
# 私有屬性在外面無法直接訪問,因此只需要在內部定義一個可以在外部調用的方法,然后在外面調用即可
print("通過定義 show_status() 訪問到了私有屬性 __life_value:%s" % self.__life_value)
def shot(self): # 動態屬性
# 為什么這里有個 self
# 為了告訴這個函數,'誰'調用了這個方法
# 這里面的'誰'就是'實例化名',也就是r1,r2
# r1.shot() == Role.shot(r1)
print("shooting...")
def got_shot(self):
print("ah...,I got shot...")
def buy_gun(self, gun_name):
print("%s just bought %s" % (self.name, gun_name))
r1 = Role('Alex', 'police', 'AK47') # 實例化(初始化一個類,造了一個對象)
r2 = Role('Jack', 'terrorist', 'B22')
r1.buy_gun("Gatling") # Alex just bought Gatling
# del r1 # 刪除 r1
# 補充個垃圾回收機制和 __del__ 析構函數
# 進行這個操作后,r1 變量被刪除,但 r1 所引用的內存還存在
# Python 通過垃圾回收機制定期循環內存,發現 r1 引用的內存地址還在,但 r1 已經沒了
# 因此會認定 r1 內存地址已經沒有用了,隨即進行刪除
# __del__ 析構函數就在此時觸發
r2.buy_gun(("Gatling"))
# print(r1.__life_value) # 報錯
r1.show_status()
# Alex just bought Gatling
# Jack just bought Gatling
# 通過定義 show_status() 訪問到了私有屬性 __life_value:100
# Alex 觸發析構函數
# Jack 觸發析構函數
繼承
class SchoolMember(object):
members = 0 # 初始學校人數為0
def __init__(self, name, age):
self.name = name
self.age = age
def tell(self):
pass
def enroll(self):
'''注冊'''
SchoolMember.members += 1
print("\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m " % (
self.name, SchoolMember.members))
def __del__(self):
'''析構方法'''
print("\033[31;1mmember [%s] is dead!\033[0m" % self.name)
class Teacher(SchoolMember):
def __init__(self, name, age, course, salary):
# SchoolMember.__init__(self, name, age)
super(Teacher, self).__init__(name, age) # 與上面一樣,在子類中重構父類的方法
self.course = course
self.salary = salary
self.enroll()
def teaching(self):
'''講課方法'''
print("Teacher [%s] is teaching [%s] for class [%s]" % (self.name, self.course, 's12'))
def tell(self):
'''自我介紹方法'''
msg = '''Hi, my name is [%s], works for [%s] as a [%s] teacher !''' % (self.name, 'Oldboy', self.course)
print(msg)
class Student(SchoolMember):
def __init__(self, name, age, grade, sid):
super(Student, self).__init__(name, age)
self.grade = grade
self.sid = sid
self.enroll()
def tell(self):
'''自我介紹方法'''
msg = '''Hi, my name is [%s], I'm studying [%s] in [%s]!''' % (self.name, self.grade, 'Oldboy')
print(msg)
if __name__ == '__main__':
t1 = Teacher("Alex", 22, 'Python', 20000)
t2 = Teacher("TengLan", 29, 'Linux', 3000)
s1 = Student("Qinghua", 24, "Python S12", 1483)
s2 = Student("SanJiang", 26, "Python S12", 1484)
t1.teaching()
t2.teaching()
t1.tell()
-
繼承策略:
D繼承BC;B、C繼承A
1.廣度優先(Python3 默認繼承方式):D - B - C - A
2.深度優先(Python2 經典類按深度優先,新式類按廣度優先): D - B - A,D - C - A
廣度優先 - 繼承
class A(object): # class A: 經典類
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
class C(A):
def __init__(self):
print("C")
class D(B,C):
pass
D() # B
- 多態:為了實現接口的重用,一個接口,多種實現
# Author:Gatling
class Animal(object):
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
print('%s: 喵喵喵!' % self.name)
class Dog(Animal):
def talk(self):
print('%s: 汪!汪!汪!' % self.name)
def func(obj): # 一個接口,多種形態
obj.talk()
c1 = Cat('小晴')
d1 = Dog('李磊')
func(c1)
func(d1)
2018-02-03
XML 模塊
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
# 遍歷xml文檔
for child in root:
print(child.tag, child.attrib)
for i in child:
print(i.tag, i.text)
# 只遍歷year 節點
for node in root.iter('year'):
print(node.tag, node.text)
- 修改 + 刪除
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
#修改
for node in root.iter('year'): # 找到 year
new_year = int(node.text) + 1
node.text = str(new_year)
node.set("updated","yes") # 添加屬性
tree.write("xmltest.xml")
#刪除node
for country in root.findall('country'): # 找到所有的 country
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country) # 刪除 node
tree.write('output.xml')
- 查找
import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist") # Element 根節點
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) # SubElement 子節點
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
et = ET.ElementTree(new_xml) # 生成文檔對象
et.write("test.xml", encoding="utf-8",xml_declaration=True) # xml_declaration 聲明這是 xml 格式的
ET.dump(new_xml) # 打印生成的格式
ConfigParser 模塊:解析配置文件
hashlib 模塊:加密相關
hmac 模塊:加密進階版
tips
- ctrl+shift+n 查找文件
- ctrl+n
re 模塊:正則
'.' 默認匹配除\n之外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
'^' 匹配字符開頭,若指定flags MULTILINE,這種也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符結尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*號前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 結果為['abb', 'ab', 'a']
'+' 匹配前一個字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 結果['ab', 'abb']
'?' 匹配前一個字符1次或0次
'{m}' 匹配前一個字符m次
'{n,m}' 匹配前一個字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結果'ABC'
'(...)' 分組匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 結果 abcabca456c
'\A' 只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符結尾,同$
'\d' 匹配數字0-9
'\D' 匹配非數字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 結果 '\t'
-
'(?P<name>...)'
分組匹配 :配合 groupdict() 實現為匹配的字符加上 key 鍵
re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
# 結果
{'province': '3714', 'city': '81', 'birthday': '1993'}
- 一些常用的方法
re.match 從頭開始匹配(只匹配第一個)
re.search 匹配包含(只匹配第一個)
re.findall 把所有匹配到的字符放到以列表中的元素返回 ,匹配不到是空數組 [] , ['']是匹配到了
re.split 以匹配到的字符當做列表分隔符
>>> re.split("\d+","a1b22c333d4444e")
['a', 'b', 'c', 'd', 'e']
>>> re.split("\d","a1b22c333d4444e")
['a', 'b', '', 'c', '', '', 'd', '', '', '', 'e']
re.sub 匹配字符并替換
- res = re.match()
res.group():匹配到的字符串
2018-02-02
標準庫 - shutil 模塊
# Author:Freeman
import shutil
# f1 = open('note', encoding="utf-8") # 有這個文件
# f2 = open('note2', 'w', encoding='utf-8') # 沒有這個文件,創建一個
# shutil.copyfileobj(f1, f2) # 把 f1 的內容復制一份到 f2
shutil.copyfile('note2', 'note3') # 直接復制一個文件的副本(note3)
# shutil.copystat(src, dst) # 拷貝:mode bits,atime,mtime,flags
# shutil.copy() # 拷貝文件和權限
# shutil.copy2() # 拷貝文件和狀態信息
# shutil.copytree(原目錄,目標目錄) # 完整的拷貝目錄
# shutil.rmtree() # 刪除目錄
# shutil.move() # 移動文件
# shutil.make_archive("壓縮", 'zip', r'D:\ForPython\2018-1-30') # 創建壓縮包并返回路徑
shelve 模塊
2018-02-01
標準庫 - random
import random
random.randint(1,10) # 隨機 [1,10] 的整數
random.randrange(1,10) # 隨機 (1,10) 的整數
random.choice(seq)
標準庫 - os
- 常用方法
# Author:Freeman
import os
print(os.getcwd()) # 當前路徑:D:\ForPython\2018-02-01
os.chdir(r"D:\ForPython\2018-02-01") # 切換路徑:命令行中為了避免轉義,需要兩個\\ ,也可以 r'D:\ForPython'
print(os.getcwd()) # D:\ForPython
print(os.curdir) # 當前目錄 .
print(os.pardir) # 上一級目錄 ..
os.makedirs(r'a\b\c') # 遞歸創建目錄(可以指定任意路徑)
os.removedirs(r'a\b\c') # 遞歸刪除目錄
# 刪除目錄(主要用于清理空目錄):
# 1.檢查c是否為空,是則刪除c
# 2.檢查b是否為空,是則刪除b
# 3.檢查a是否為空,是則刪除a
os.mkdir(r"E:\abc") # 創建目錄(可以指定任意路徑)
os.rmdir(r"E:\abc") # 刪除單個目錄
print(os.listdir()) # 返回當前目錄下的文件組成的一個 list(包括隱藏文件)
# os.rename(r'D:\ForPython\2018-02-01\level2_change', r'D:\ForPython\2018-1-31\level2') # 把參數1的文件轉移到參數2,支持改名
os.stat("os.py") # 獲取文件 / 目錄信息
os.environ # 查看環境變量
os.name # 當前系統名
os.path.abspath()
os.path.split(r"D:\a\b\c\d.txt") # 返回:('D:\a\b\c','d.txt') (不考慮文件是否存在)
os.path.basename(r"D:\a\b\c.txt") # 返回:'c.txt' (不考慮文件是否存在)
os.path.exists() # 判斷路徑是否存在
os.path.isabs() # 是否為絕對路徑(Windows 以盤符開始,Linux以 / 開始)
os.path.isfile() # 是否為一個文件
os.path.isdir() # 是否為一個目錄
os.path.join(r'C:',r'\a.txt') # 'C:\a.txt'
os.path.getatime() # 文件或目錄的最后存取時間
os.path.getmtime() # 文件或目錄的最后修改時間
- 特別說明:由于 Windows 和 Linux 操作系統的路徑規范不一致,
Name | Windows | Linux |
---|---|---|
路徑斜杠 | \ | / |
換行 | \r\n | \n |
文件路徑分隔符 | ; | : |
-
os.system(command)
os.system()
標準庫 - sys 模塊
tips
2018-1-31
標準庫 - time 模塊
- 忘了有什么方法可以使用 help()
- 時間戳 / Structure_time(tuple 格式) / 格式化字符串
1.時間戳 => 元祖 localtime(),gmtime()
2.元祖 => 時間戳 mktime()
3.元祖 => 指定字符串時間格式 strftime()
4.指定字符串時間格式 => 元祖 strptime()
5.時間戳=>字符串 asctime([tuple]),ctime([seconds])
# time 具有的方法
time() -- return current time in seconds since the Epoch as a float
clock() -- return CPU time since process start as a float
sleep() -- delay for a number of seconds given as a float
gmtime() -- convert seconds since Epoch to UTC tuple
localtime() -- convert seconds since Epoch to local time tuple
asctime() -- convert time tuple to string
ctime() -- convert time in seconds to string
mktime() -- convert local time tuple to seconds since Epoch
strftime() -- convert time tuple to string according to format specification
strptime() -- parse string to time tuple according to format specification
tzset() -- change the local timezone
- 時間戳格式化為指定格式
# Author:Freeman
import time
Epoch_time = time.time()
time_tuple = time.localtime(Epoch_time)
format_time = time.strftime("%Y-%m-%d %H:%M:%S", time_tuple) # %Y 不是位置對應,%Y 放哪里都是年
print(Epoch_time)
print(time_tuple)
print(format_time)
# 1517414160.0117865
# time.struct_time(tm_year=2018, tm_mon=1, tm_mday=31, tm_hour=23, tm_min=56, tm_sec=0, tm_wday=2, tm_yday=31, tm_isdst=0)
# 2018-01-31 23:56:00
- 時間格式的符號說明
%a 本地(locale)簡化星期名稱
%A 本地完整星期名稱
%b 本地簡化月份名稱
%B 本地完整月份名稱
%c 本地相應的日期和時間表示
%d 一個月中的第幾天(01 - 31)
%H 一天中的第幾個小時(24小時制,00 - 23)
%I 第幾個小時(12小時制,01 - 12)
%j 一年中的第幾天(001 - 366)
%m 月份(01 - 12)
%M 分鐘數(00 - 59)
%p 本地am或者pm的相應符 一
%S 秒(01 - 61) 二
%U 一年中的星期數。(00 - 53星期天是一個星期的開始。)第一個星期天之前的所有天數都放在第0周。 三
%w 一個星期中的第幾天(0 - 6,0是星期天) 三
%W 和%U基本相同,不同的是%W以星期一為一個星期的開始。
%x 本地相應日期
%X 本地相應時間
%y 去掉世紀的年份(00 - 99)
%Y 完整的年份
%Z 時區的名字(如果不存在為空字符)
%% ‘%’字符
標準庫 - datetime 模塊
# Author:Freeman
import datetime
_now = datetime.datetime.now()
_future_day = datetime.datetime.now() + datetime.timedelta(3)
_ago_day = datetime.datetime.now() + datetime.timedelta(-3)
_future_hours = datetime.datetime.now() + datetime.timedelta(hours=3)
_future_minutes = datetime.datetime.now() + datetime.timedelta(minutes=15)
_ago_minutes = datetime.datetime.now() + datetime.timedelta(minutes=-15)
print(_now) # 2018-02-01 00:32:21.502319
print(_future_day) # 2018-02-04 00:32:21.502319
print(_ago_day) # 2018-01-29 00:32:21.502319
print(_future_hours) # 2018-02-01 03:32:21.502319
print(_future_minutes) # 2018-02-01 00:47:21.502319
print(_ago_minutes) # 2018-02-01 00:17:21.502319
關于導入包
- 導入包實際上是導入包內的
__init__.py
文件,因此需要在__init__.py
中進一步導入子包或模塊
目錄結構
現在想為grandpa.py
導入son.py
,步驟如下:
# grandpa.py
import level2
# level2 包內的 __init.py__
from . import level3
# level3 包內的 __init.py__
from . import son
# son.py
text = "調用成功!"
# grandpa.py 中調用 son 中的方法
print(level2.level3.son.text) # 調用成功!
tips
-
Structure 界面可以顯示當前文件的變量和函數,打開方法:
1.alt+7
2.view - Tool Windows - Structure
Structure -
在 Project 視圖中,讓文件顯示包括的方法
Show Members -
import module_A
再通過module_A.func
調用模塊內的func
方法是先找到module_A
再引用func
方法,如果引用 N 次func
,則在找module_A
上會浪費掉大量的時間,因此針對這種情況,如果只引用func
方法,則使用from module_A import func
會減少找文件的時間
2018-1-30
模塊
- 定義:本質就是 .py 結尾的 Python 文件,目的就是為了實現某個功能(文件名為
test.py 則模塊名為 test) - 導入模塊方法
# 第一種導入
import module1,module2 # 導入多個模塊
module1.func() # 調用
# 第二種導入
from module import func # 導入所有變量和函數(不建議,重名)
from module import func1,func2,func3
func() # 調用 不能 module1.func(),因為導入的是模塊里的所有內容
# 第三種導入
from module import func as another_func # 起個別名
another_func() # 調用
# 第四種導入
from . import func # 從當前目錄下導入 func
- import 本質:相當于把 A模塊內所有的代碼統一賦給變量 A
- from module import func:相當于直接把 module 中的 func 代碼賦給一個 func 變量
- 包的定義:從邏輯上組織模塊,本質就是一個目錄(必須帶有一個 init.py 的文件)
- 導入包文件實際上就是執行包內的
__init__.py
文件(只是當前包內的__init__py
)
導入包
2018-1-28
Python 內置方法
- abs(): 絕對值
- all():全真反真
# Author:Freeman
list = [0, 1, 2, 3]
print(all(list)) # True
- any():有真反真
- ascii():
- bin():十進制整數轉二進制
- bool():布爾值
- bytearray():返回 ascii 碼,并且可通過為元素賦不同的 ascii 碼值來改變(常規的str和二進制是無法在原對象上改變的,都是創建一個副本)
# Author:Freeman
a = bytes("abcde", encoding="utf-8")
b = bytearray("abcde", encoding="utf-8")
print(a.capitalize(), a)
print(b[0]) # ascii 碼
b[0] = 98
print(b)
# b'Abcde' b'abcde'
# 97
# bytearray(b'bbcde')
- callable():判斷是否可調用,例如函數就可通過 ()調用,list 沒法調用
- chr():傳入 ascii 碼值,返回對應符號
- ord():傳入 符號,返回 ascii 值
- compile():跟 js 的 eval 差不多
- dir(對象) 查看對象可以調用的方法
- divmod():返回商和余數
- eval():
- exec():
- filter():過濾
# Author:Freeman
express = lambda n: n > 5
res = filter(express, range(10))
print(type(res)) # <class 'filter'>
for i in res:
print(i)
# <class 'filter'>
# 6
# 7
# 8
# 9
- map():
# Author:Freeman
express = lambda n: n * n
res = map(express, range(5))
print(type(res)) # <class 'map'>
for i in res:
print(i)
# <class 'map'>
# 0
# 1
# 4
# 9
# 16
- reduce():意思就是對sequence連續使用function, 如果不給出initial, 則第一次調用傳遞sequence的兩個元素, 以后把前一次調用的結果和sequence的下一個元素傳遞給function. 如果給出initial, 則第一次傳遞initial和sequence的第一個元素給function.
# Author:Freeman
import functools
express = lambda x, y: x + y
res = functools.reduce(express, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 計算過程 ((((((((0 + 1) + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9
print(res)
# 45
- lambda表達式:
lambda n:3 if n<4 else n
# n 小于 4 就是 3,否則就是 n
frozenset([iterable]):不可變集合,用了之后集合就不能進行添加刪除
globals():返回當前文件內所有的全局變量和值的 dict 格式
locals():返回當前局部作用于內的變量和值
hash():將參數轉換為 hash 值,為了方便排序后的 折中查找
hex():轉成十六進制
oct():八進制
max():
min():
pow():冪
reversed():反轉
round():保留幾位小數
slice():
sorted():排序
zip():
# Author:Freeman
key = ["a", "b", "c", "d"]
val = [9, 5, 2, 7]
for i in zip(key, val):
print(i)
# ('a', 9)
# ('b', 5)
# ('c', 2)
# ('d', 7)
序列化(dumps) / 反序列化(loads)
- dumps / loads 操作只進行一次,多次 dumps 的確可以存入多個 json 字符串,但沒法正確 loads
- json
# Author:Freeman
import json
def sayhi():
print("hello,", name)
jsonObj = {
"name": "kaka",
"age": "18",
# "func":sayhi # 會報錯,不支持這種方式
}
f = open("yesterday", "r", encoding="utf-8")
# f.write(json.dumps(jsonObj)) # str
json.loads(f.read()) # dict
- pickle:是以 bytes 類型寫入或者讀取,因此 open 的方式必須為 wb 或 rb 等二進制讀寫
# Author:Freeman
import pickle
def sayhi(name):
print("hello,", name)
pickleObj = {
"name": "kaka",
"age": "18",
"func": sayhi
}
f = open("yesterday", "wb")
f.write(pickle.dumps(pickleObj)) # pickle.dump(pickleObj,f) # 效果一樣
以上代碼存在于文件A,但在另一個文件B中去讀 yesterday 這個文件會報錯,因為 sayhi 這個函數只是存在于文件A之中,在文件B中是找不到 sayhi 的內存地址,除非在B中定義一個同名的 sayhi 函數
python 建議項目結構
Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
簡要解釋一下:
#
# bin/: 存放項目的一些可執行文件,當然你可以起名script/之類的也行。
# foo/: 存放項目的所有源代碼。(1) 源代碼中的所有模塊、包都應該放在此目錄。不要置于頂層目錄。(2) 其子目錄tests/存放單元測試代碼; (3) 程序的入口最好命名為main.py。
# docs/: 存放一些文檔。
# setup.py: 安裝、部署、打包的腳本。
# requirements.txt: 存放軟件依賴的外部Python包列表。
# README: 項目說明文件。
# 除此之外,有一些方案給出了更加多的內容。比如LICENSE.txt,ChangeLog.txt文件等,我沒有列在這里,因為這些東西主要是項目開源的時候需要用到。如果你想寫一個開源軟件,目錄該如何組織,可以參考這篇文章。
跨文件調用
-
想從 atm.py 中調用 main.py 的方法
項目結構
# atm.py
# print(__file__) # 相對路徑, pycharm 中顯示的是絕對路徑
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath((__file__))))
# __file__ 代表當前文件
# os.path.abspath 絕對路徑 D:\ForPython\atm\bin\atm.py
# os.path.dirname 當前文件所在的目錄名,這里向上找了兩次
sys.path.append(BASE_DIR) # 添加環境變量
# sys.path 本身返回的是一個當前文件能訪問到的路徑組成的一個 list,
# 因此只要在這個 list 中添加一個新模塊的路徑,在當前文件中就可以 import 新模塊
# 這里還有個問題,新插入的路徑在最后面,如果在之前有重名的模塊就不會調用到預期的模塊,但由于是 list,可以不采取 append 而是 insert 之類的方法
from conf import settings
from core import main
main.info()
# 你已經成功調取到 main.py 的內容!
# main.py
def info():
print("你已經成功調取到 main.py 的內容!")
2018-1-27
tips
- alt + 鼠標左鍵可以創建多個光標
生成器 generator
- 為什么要使用生成器?
比如有一個具有幾十億個元素的 list,如果想把 list 賦值給變量 a,會消耗很長的時間,list 也會占用很大的內存。generator 的存在就是為了解決這個問題,先 準備 出一個具有幾十億元素的 generator (相當于告訴內存,我要你先準備一個列表,但你現在不用創建出來,等我需要用到哪個的時候再去找你,到時候你只需要給我我要的東西就可以),但并不占用內存,只有當調用 generator 中具體某個值時,那個值才會存在于內存之中 - generator 只有在調用的時候才生成相應的數據,所以沒辦法使用切片或者 list 的常規操作
- generator 具有
__next__
方法(Python3.0,2.7為 next()),且只能一個一個的往后找,不能返回,不能跳過
# Author:Freeman
generator = (i for i in range(10))
print(generator)
print(generator.__next__())
print(generator.__next__())
# <generator object <genexpr> at 0x000002E245B288E0>
# 0
# 1
列表生成式
- 常規
# Author:Freeman
a = [i + 2 for i in range(10)]
print(a)
# [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
- 函數
# Author:Freeman
def func(*args):
answer = "哈哈 %s" % args
return answer
a = [func(i) for i in range(10)]
print(a)
生成器 + 異常處理
- yield 用于保存函數的中斷狀態
# Author:Freeman
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 有 yield 的存在,fib 就已經是一個生成器了,而 b 就是生成器中的元素
a, b = b, a + b
n = n + 1
return "----done----" # 用于捕獲錯誤
g = fib(5)
# 異常捕獲
while True:
try:
# x = next(g) # 在 3.0 中這句也好用
x = g.__next__()
print("g:", x)
except StopIteration as e: # 捕獲 StopIteration 錯誤
print("Generator return value:", e.value)
break
# g: 1
# g: 1
# g: 2
# g: 3
# g: 5
# Generator return value: ----done----
- 生成器例子
# Author:Freeman
import time
def consumer(name):
print("[%s]來吃包子了!" % name)
while True:
ab = yield
print("[%s]包子來了,但是[%s]并沒有吃到包子" % (ab, name))
c = consumer("大飛哥")
c.__next__() # [大飛哥]來吃包子了!
c.__next__() # [None]包子來了,但是[大飛哥]并沒有吃到包子
c.__next__() # [None]包子來了,但是[大飛哥]并沒有吃到包子
c.send("韭菜餡") # [韭菜餡]包子來了,但是[大飛哥]并沒有吃到包子
c.send("面餡") # [面餡]包子來了,但是[大飛哥]并沒有吃到包子
c.__next__() # [None]包子來了,但是[大飛哥]并沒有吃到包子
- 生成器例子(協程)
# Author:Freeman
import time
def consumer(name):
print("[%s]來吃包子了!" % name)
while True:
ab = yield
print("[%s]包子來了,但是[%s]并沒有吃到包子" % (ab, name))
list = ["韭菜餡", "面餡"]
def producer(name):
c = consumer("A")
c2 = consumer("B")
c.__next__()
c2.__next__()
print("[%s]開始準備做包子啦!" % name)
for i, item in enumerate(list):
time.sleep(1)
print("%s做了兩個包子!"%name)
c.send(item)
c2.send(item)
producer("大帥哥")
# [A]來吃包子了! # consumer
# [B]來吃包子了! # consumer
# [大帥哥]開始準備做包子啦! # producer
# [大帥哥]做了兩個包子! # producer
# [韭菜餡]包子來了,但是[A]并沒有吃到包子 # consumer
# [韭菜餡]包子來了,但是[B]并沒有吃到包子 # consumer
# [大帥哥]做了兩個包子! # producer
# [面餡]包子來了,但是[A]并沒有吃到包子 # consumer
# [面餡]包子來了,但是[B]并沒有吃到包子 # consumer
迭代器
- 可直接作用于 for 循環的對象
1.list ,tuple,set,dict,str
2.generator:包括生成器和帶 yield 的 generator function
以上兩類統稱為可迭代對象:Iterable,可以使用 isinstance() 判斷一個對象是否為 Iterable 對象 - 迭代器(Iterator):可以被 next() 函數調用并不斷返回下一個值的對象
- generator 都是 Iterator 對象,但 list、dict、set 雖然是 Iterable,但卻不是 Iterator,可以使用 iter() 方法將 list、dict、set 變為 Iterator
裝飾器
- 帶參數的裝飾器,不是很理解,先放這里吧
# Author:Freeman
import time
user, passwd = "kaka", "123"
def auth(auth_type):
def outer_wrapper(func):
def wrapper(*args, **kwargs):
if auth_type == "local":
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
return func(*args, **kwargs)
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif auth_type == "ldap":
print("搞毛線?")
return wrapper
return outer_wrapper
def index():
print("welcome to index page")
@auth(auth_type="local")
def home():
print("welcome to home page")
return "from home"
@auth(auth_type="ldap")
def bbs():
print("welcome to bbs page")
# index()
# print(home())
home()
# bbs()
2018-1-26
裝飾器
- 高階函數(返回函數地址的函數)+ 嵌套函數
- 下面代碼中 timer 就是裝飾器,滿足了兩個條件:
1.不改變 test1 的內容;
2.不改變 test1 的調用方式 - 裝飾器作用于緊鄰它的第一個函數
# Author:Freeman
import time
def timer(func):
def deco():
start_time = time.time()
func()
end_time = time.time()
print("func run time is %s" % (end_time - start_time))
return deco
@timer # 裝飾器,之后直接調用 test1 就是攜帶裝飾器的調用,裝飾器作用于緊鄰它下面的第一個函數
def test1():
time.sleep(2)
print("this is test1 func")
test1()
# timer(test1)() # 如果不用裝飾器,也可以這么寫
- 如何攜帶參數?
# Author:Freeman
import time
def timer(func):
def deco(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("func run time is %s" % (end_time - start_time))
return deco
@timer
def test1(*args, **kwargs):
time.sleep(2)
print("this is test1 func:", *args, **kwargs)
# timer(test1)()
# test1 = timer(test1) # 不要考慮那些亂七八糟的,timer 執行返回 deco 地址,test1 就是 deco 地址,再進一步說,調用 test1 就是調用 deco
test1("kaka", {"dict_key": 5})
- 為什么沒有返回值 "from home"?該怎么做,為什么?
# Author:Freeman
import time
user, passwd = "kaka", "123"
def auth(func):
def wrapper(*args, **kwargs):
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
func(*args, **kwargs)
else:
exit("\033[31;1mInvalid username or password\033[0m")
return wrapper
def index():
print("welcome to index page")
@auth
def home():
print("welcome to home page")
return "from home" # 為什么這行沒有返回?打印結果中的 None 是哪來的?
@auth
def bbs():
print("welcome to bbs page")
index()
print(home())
bbs()
# welcome to index page
# Username:kaka
# Password:123
# User has passed authentication
# welcome to home page
# None # 這是什么鬼?from home 呢?
# Username:
# 解釋:
# 如上個例子所言,調用 home 就等于調用 wrapper
# 然而 home 有返回值,裝飾器中 wrapper 中的 home() 也的確進行了調用并返回了 from home,但是 wrapper 沒有 return
# 可以理解為 wrapper 中已經包含了 home 的返回值 from home ,但是 wrapper 沒有把 這個 from home 的結果 return 出來
# 沒有 return 語句的函數默認返回值為 None
# 注意:return wrapper 是 auth 的返回值,不是 wrapper 的
2018-1-25
tips
- y=x=1,1一直在內存中,可以通過x,y來找到1的內存地址。使用 del 可以刪除 x,y 而1不會被 del 刪除,當 1 沒有任何引用的時候,Python 內部的定時回收機制會刪除 1
裝飾器
- 定義:本質是函數,用于裝飾其它函數——為其它函數添加附加功能
- 原則:
1.不能修改被裝飾函數的源代碼
2.不能修改被裝飾函數的調用方式 - 通俗的講,裝飾器可以讓函數在不知情的情況下發生改變
- 實現裝飾器的知識儲備:
1.函數即是變量
2.高階函數:a.把函數名當做一個實參傳給另一個函數;b.返回值中包含函數名
3.嵌套函數
高階函數+嵌套函數 => 裝飾器
2018-1-24
- int 是 向0取整
遞歸
- 必須要有一個明確的結束條件
- 每次進入更深一層的遞歸時,問題的規模相比上一次遞歸都應該有所減少
- 遞歸效率不高,遞歸次數過多會導致棧溢出
- 做遞歸用 斷點 調試
函數
- 默認參數
# Author:Freeman
def func(x, y, z=3):
print(x)
print(y)
print(z)
func(2, 1, "kk")
# 輸出 2,1,kk
- 非固定參數 * + 形參,*args 接收 位置參數 轉換成 元祖
# Author:Freeman
def func(*args):
print(args)
print(args[1])
print(len(args))
func(2, 1, "kk")
# (2, 1, 'kk')
# 1
# 3
# Author:Freeman
def dict(name, age=12, *args):
print(name)
print(age)
print(args)
dict(*["lky", "222", "gogogo"])
# lky
# 222
# ('gogogo',)
- 接受字典參數 ** + 形參,兩種方式傳參,**kwargs 部分只能接收 關鍵字參數(a=3 這種) 轉換成 字典
# Author:Freeman
def dict(**kwargs):
print(kwargs)
dict(name="xxx", age="123", salary="沒有") # 第一種
dict(**{"name" : "xxx", "age" : "123", "salary" : "沒有"}) # 第二種
# {'name': 'xxx', 'age': '123', 'salary': '沒有'}
# {'name': 'xxx', 'age': '123', 'salary': '沒有'}
**kwargs 參數組往后放:當關鍵字參數合法時,不會被當做字典參數
# Author:Freeman
def dict(name, age=12, **kwargs):
print(name)
print(age)
print(kwargs)
dict(name="lky",age="222",key="gogogo")
# lky
# 222
# {'key': 'gogogo'}
- 在局部作用域修改全局變量:global 。避免使用 global 在局部作用于聲明全局變量
# Author:Freeman
abc = 12
def change(param=3):
global abc # 這里不能寫賦值
abc = 11
print(abc) # 這里不能寫賦值
change()
# 11
2018-1-23
編程方式
- 面向對象
核心是 類,定義它的關鍵字就是 class - 面向過程
過程,def:實際上就是沒有返回值的函數,Python 解釋器隱式的返回 None。而面向過程的編程方式實際上就是用許多沒有返回值的函數組成的一種編程方式。 - 函數式編程
函數, def:有返回值
函數
- 直接傳參 / 位置調用
- 位置調用需要與形參一一對應
- 位置調用與關鍵字調用混用時,應保證位置參數在前,最好別這么混著用
# Author:Freeman
def func(x, y):
print(x)
print(y)
# func(1, 2)
func(y=1, x=2)
輸出時間
# Author:Freeman
import time
rule = "%Y-%m-%d %X"
time = time.strftime(rule)
print(time)
# 輸出 2018-01-23 23:08:23
2018-1-22
打印系統默認編碼
- sys.getdefaultcoding()
ASCII Unicode utf-8 的區別
- 不同國家的編碼互相轉換都需要先轉換成 Unicode:比如中國的GBK編碼,需要先解碼為 Unicode 再編碼成其他國家的編碼
有個圖不錯,去找一下
with
- 無需再寫關閉文件語句,with 語句執行完后文件就被關閉
- Python2.7 之后 with 語句可以打開多個文件
- Python 官方書寫規范,通過 反斜杠 \ 換行
# Author:Freeman
import sys
with open("yesterday", "r", encoding="utf-8") as f, \
open("yesterday2", "r", encoding="utf-8") as f2:
for i in f:
print(i.strip())
tips
- 為什么需要在代碼中關閉文件?
盡管在你關閉程序時,Python 的垃圾回收機制會自動收回打開文件所占用的內存,但如果你打開N多個文件,如果不通過代碼關閉文件的占用,則這個文件會一直占用內存。
sys.argv
- sys.argv:
# Author:Freeman
import sys
item = sys.argv
print(item)
print(item[0])
print(item[1])
print(item[2:])
- 一個查找并替換文件內容的方法
# Author:Freeman
import sys
f = open("yesterday", "r+", encoding="utf-8")
old_str = sys.argv[1]
new_str = sys.argv[2]
for line in f:
if old_str in line:
line = line.replace(old_str, new_str)
print(line)
之前的
快捷鍵
- ctrl + alt + L 代碼格式化
- ctrl + B 跳轉到源代碼 或者 按住 ctrl+左鍵
- ctrl + w 逐漸擴選代碼塊,ctrl + shift + w 反之
- ctrl + / - 展開 / 折疊代碼 ,加 shift 就是全部展開 / 折疊
input()
- 導入模塊,getpass 在 pycharm 中不好使
- input("123") 中輸入的結果會被當做 字符串,轉換為數字需要 int(input("123"))
# Author:Liu
import getpass
_username = "lky"
_password = "123"
username = input("name:")
password = getpass.getpass("password:")
if _username == username and _password == password:
print("Welcome {name} login".format(name=username)) # 字符串連接
else:
print("Invalid username or password")
循環 判斷 跳出循環
- while,for 都可以搭配 else
# Author:Liu
age_of_oldboy = 56
while True:
guess_age = int(input("guess age:"))
if guess_age == age_of_oldboy:
print("yes ,you got it.")
break
elif guess_age > age_of_oldboy:
print("think smaller...")
else:
print("think bigger!")
range()
- range(開始,結束,步長)
# Author:Liu
for i in range(1, 10, 3):
print(i) # 1,4,7
打斷點
模塊(庫)
標準庫:直接可用,比如 getpass
第三方庫:例如 Django
文件名避免與庫名重復
-
sys 模塊
1.sys.path:環境變量
2.sys.argv:當前腳本的相對路徑(Pycharm 中由于軟件設置,會打印絕對路徑)
sys 模塊(site-packages 為第三方庫存放地址,lib 層為標準庫存放地址) -
os 模塊:一般用于與系統的交互
1.os.system("dir"):用于直接顯示當前文件所在目錄的所有文件,之后返回結果,0 代表成功
os.system("dir")
# 一些常用的 os 方法
# Author:Liu
import os
# cmd_res = os.system("dir") # 執行命令,無法保存結果
# cmd_res = os.popen("dir") # 內存對象地址
# cmd_res = os.popen("dir").read() # 讀取地址
os.mkdir("new_dir_by_python") # 創建目錄
print("-->", cmd_res)
.pyc 是什么?
- .pyc 文件是 Python 的編譯后的 字節碼文件,它還不是機器碼,甚至算不上 “半成品”
- 程序第一次運行后產生 .pyc 文件,下次再運行時就不需要重新編譯,直接調用 .pyc 文件
- 當保存了 .pyc 文件之后,對源文件又做了改動,這時 Python 會根據源文件和 .pyc 文件的最后更新時間來判斷文件是否經過改動
數據類型
- type() 查看數據類型
- ** 冪
- int 整形 ,long 長整型,float 浮點型,布爾,字符串,bytes 類型
- 視頻,音頻的二進制傳輸類型為 bytes
- python3 沒有長整形 long
三元運算
result = 值1 if 條件1 else 條件2
十六進制表示法
- 0x 前綴,或者 H 作為后綴
編碼和解碼
- 需要編碼.encode(想要轉換成那種編碼)
- 需要解碼.decode(之前的編碼集)
- Python3 中 encode() 之后都會變成 bytes 類型
- 所有的 .decode() 動作都是要解碼為 Unicode
切片
- 切片也可以跳著切,[起點:終點:步長]
# Author:Liu
names = ["a", "b", "c", "d"]
print(names[0])
print(names[1:2])
print(names[1:])
print(names[-2:])
names.insert[1,"abc"] # 插入
names[2] = "aaaa" # 替換
del names[1] # 刪除 也可以刪除變量
names["c"] # 刪除
- append():最后添加
- pop([index]):刪除,不寫參數默認刪除最后一個
- insert(位置,需要插入的元素)
- index("xxx") 位置
- count("xxx") 數量
- list.clear() 清空
- copy() 淺拷貝,只復制第一層,是復制,復制完就變成兩個獨立的 第一層!
# Author:Liu
import copy
names = ["name", ["saving"]]
# 淺copy的三種方式
names2 = copy.copy(names)
names2 = names[:]
names2 = list(names)
# 淺copy的用途 —— 聯合賬號
names[0] = "husband"
names2[0] = "wife"
names[1][0] = 5000
print(names) #['husband', [5000]]
print(names2) #['wife', [5000]]
- 深拷貝:將數據完全拷貝一份,互不影響,沒有引用問題
# Author:Liu
import copy
# 深copy
names = ["a", "b", "b", [1, 2], "c", "d"]
names2 = copy.deepcopy(names)
names2[3][1] = "bbbbb"
print(names[3][1])
元祖(只讀列表)
- 不能改的列表
- 只有兩個方法,count(),index()
.isdigital()
- .isdigital():純整數 的字符串,返回:true,false。
enumerate()
- for index,item in enumerate(list) 跟 jQuery 的 each 循環差不多
字符串操作,注意,是字符串的方法
- capitalize():首字母大寫
- count():計數
- center():一共 xx 個字符,不夠的話用指定字符填充,如果是兩邊不對等,字符串右側多一個
# Author:Liu
name = "123"
print(name.center(40, "-"))
# ------------------123-------------------
- encode()
- endswith():字符串以什么結尾
- expendtabs():當字符串中有 \t 時,可在方法內添加 tabsize=12 來替換字符串中的 \t
- find():返回查詢字符串的第一個字符的位置
- format():格式化嵌入數據
- format_map():參數傳一個 字典
# Author:Liu
name = "My name is {name},I'm {age} years old"
print(name.format(name="kaka", age='2222'))
print(name.format_map({"name":"Dictionary","age":"122"}))
# My name is kaka,I'm 2222 years old
# My name is Dictionary,I'm 122 years old
- index():下標
- inalnum():只包含數字字母的字符串才是 true ,含有其它的符號均為 false
- isalpha():是否只包含純英文字符(無所謂大小寫)
- isdecimal():
- isdigit():是否整數,不支持中文數字,也支持 “壹”
- isidentifier():是否是一個合法的標識符,可以用來檢查變量名是否合法
- islower():是否是小寫
- isnumeric():是否整數,支持中文數字。注意跟 isdigit() 的對比
- isspace():是否是空格,\t,\n 也是 True
- istitle():所有單詞是否首字母大寫
- isprintable():tty file,drive file 會返回 False
- isupper():是否大寫
- join():print("-".join(["a","b","c"])),拼接
- ljust() / rjust():右側補位,左側補位,對應 center()
- lower() / upper():變小寫 / 大寫
- lstrip() / rstrip() / strip():去掉左邊 / 右邊 / 兩邊的空格或回車
1.strip() 可以從兩邊開始刪除指定的字符串
2.創建副本,不改變原字符串 - maketrans():
p = str.maketrans("abcd", "1234") # 重復的話以最后為準,數量必須一樣
print("abcd".translate(p))
# 輸出:1234
- replace():三個參數,被替換的,用于替換的,個數
- rfind():返回匹配到的結果中,最右側的結果的位置
- split():str 切割為 list
- splitlines():以 \n 切割
- swapcase():大寫變小寫,小寫變大寫
- translate():與 maketrans() 配合使用
- zfill():不夠的話前面補0
字典 Dictionary
- 字典是無序的
- key 是唯一的
- 字典的方法:
1.dict.del():刪掉一個 key,也可不寫參數刪除整個字典
2.dict.pop():刪掉指定 key,必須寫參數
3.dict.popitem():隨機刪
4.查找 dict["aaa"] 如果參數 key 不存在會報錯
5.dict.get():如果沒有參數 key 直接返回 None
5.key in dict:返回布爾值,python2.7 中是 dict.has_key("key") 。python3 中已刪除
6.setdefault():為字典添加新值,但如果添加的這個 key 原本存在則不添加
7.dict1.update(dict2):把 dict2 添加到 dict1 ,如果重復則更新,不重復則添加
8.dict.items():dict 轉 tuple (看結果只轉了第一層)
# Author:Liu
info = {
"aaa": "111",
"bbb": "222",
"ccc": "333",
"ddd": {
"ddd-1": 1,
"ddd-2": 2,
"ddd-3": 3
}
}
print(info.items())
# 輸出:dict_items([('aaa', '111'), ('bbb', '222'), ('ccc', '333'), ('ddd', {'ddd-1': 1, 'ddd-2': 2, 'ddd-3': 3})])
9.fromkeys():初始化一個 dict
test = dict.fromkeys([6, 7,"link"], {"key": "value"})
test["link"]["key"] = "new_value"
print(test)
# 輸出 {6: {'key': 'new_value'}, 7: {'key': 'new_value'}, 'link': {'key': 'new_value'}}
# 注:有引用問題
pass
- 占位符,暫時什么也不寫,避免報錯
集合及其方法
- 一種數據類型
- 沒有重復
- 無序
# Author:Freeman
list_1 = [1, 4, 5, 7, 3, 6, 7, 9]
list_1 = set(list_1)
print(set(list_1), type(list_1))
# 輸出:{1, 3, 4, 5, 6, 7, 9} <class 'set'>
- set() :轉換為集合
- intersection():取交集
- union():取并集
- difference():差集
- issubset():判斷是否是子集
- isuperset():判斷是否為父集
- symmetric_difference():A與B 的交集C,(A - C)并(B - C)
- isdisjoint():是否有交集
- & | - ^:交 并 差 對稱差
- add():添加一項 set.add(42)
- update():添加多項 set.update([1,5,3,6])
- remove():
- len(s):長度
- in / not in :判斷是否在其中
- pop():刪除并返回刪除的東西
- discard():刪除,不返回任何東西
文件操作
- open() 打開文件
- read() 讀文件
- encoding="utf-8" 用 utf-8 編碼格式打開(否則會報錯或亂碼),國內 windows 默認為 GBK 編碼
data = open("yesterday",encoding="utf-8").read()
print(data)
- 文件對象
f = open(xxx,encoding="utf-8") # 文件句柄,這里指向文件的內存地址
# Author:Freeman
f = open("yesterday","r", encoding="utf-8") # r 讀 w 寫,不寫為默認 r
data = f.read()
print(data) # print(f.read()) 不報錯但也不出結果
- 文件的模式
1.w 為重新創建(原來的就沒了),重新創建了一個名為 xxx 的文件
2.r 為只讀
3.a(append)追加 在源文件的后面追加
4.r+ 既能讀又能寫,但寫是在最后面添加
5.w+ 寫讀模式
6.a+ 追加讀寫
7.rb 二進制格式讀文件 (Python3.0里網絡傳輸只能用二進制格式)
8.wb 二進制格式寫文件
9.ab 二進制格式追加文件 - readline() 讀文件的一行,加參數為第幾列
- readlines() 將文件轉換為一個 list ,源文件的每一行為 list 中的一個元素
- write():
1.每次只寫 \n 會被合并為一個
2.如果寫完之后,通過 seek() 重新定位,下次寫的時候會覆蓋而不是把之前的內容向后推 - 讀文件的最優方式:只占一份內存
for line in f:
print(line.strip())
- tell():返回文件中的 光標 位置 1 個數字或英文字母占一個;全角數字、漢字占三個
- seek():重新設置 光標 位置。并不是所有類型的文件都可以移動光標,因此有了 seekable() 方法
- encoding():打印編碼
- flush():比如 txt 文件,通常是存儲在硬盤上,但為了保證速度,許多時候都是在緩存中進行操作,flush() 方法是強制刷新,比如涉及錢時必須保證寫了多少立刻存起來,防止突然斷電
- 一個進度效果
# Author:Freeman
import sys, time
for i in range(10):
sys.stdout.write("#")
sys.stdout.flush()
time.sleep(.5)
- truncate():無視 seek() 定位的光標,當 open 的文件為 a 時,從文件開始截取制定數量的字符,不寫參數默認全部截取