基本數據類型之set
- set是無序不允許重復的集合
- set創建:s = set() 創建空集合? s = {11,22,33}
- 轉換s = set(可迭代數據)
li = [11,22,33,44]
s = set(li)
print(s) #結果為{33, 11, 44, 22}
- 集合元素的添加與清空
se = {11,22,33}
se.add(44)
print(se) #結果為{33, 11, 44, 22}
se.clear()
print(se) #結果為set()
- set_name1.difference(set_name2) 找到name1中存在,name2不存在的元素組成新的集合
se = {11,22,33}
be = {33,55}
ret1 = se.difference(be)
ret2 = be.difference(se)
print(ret1) #結果為{11, 22}
print(ret2) #結果為{55}
- set_name1.difference_update(set_name2) 找到name1中存在,name2不存在的元素組成的集合更新給自己
se = {11,22,33}
be = {33,55}
se.difference_update(be)
print(se) #{11, 22}
- set_name1.isdisjoint(set_name2) name1和name2無交集返回Ture,有交集就返回False
se = {11,22,33}
be = {33,55}
ret = se.isdisjoint(be)
print(ret) #結果為False
- set_name1.issubset(set_name2)?? name1是否為name2的子序列
- set_name1.issuperset(set_name2)? name1是否為name2的父序列
s1 = {11,22,33,44,55}
s2 = {11,22}
ret = s2.issubset(s1) #s2是s1的子序列嗎?
print(ret) #結果為True
ret1 = s1.issuperset(s2) #s1是s2的父序列嗎?
print(ret1) #結果為True
- set_name1.symmetric_difference(set_name2)? 把兩集合相同的元素剔除,用剩下的元素組成新的集合
- set_name1.symmetric_difference_update(set_name2)? 把兩集合相同的元素剔除,用剩下的元素組成的集合賦給name1
se = {11,22,33,44}
be = {11,22,77,55}
ret = se.symmetric_difference(be)
print(ret) #結果為{33, 44, 77, 55}
se.symmetric_difference_update(be)
print(se) #結果為{33, 44, 77, 55}
- set_name.discard(元素項)和set_name.remove(元素項)? 都是移除,不過remove移除不存在的元素會報錯
se = {11,22,33,44}
se.discard(44)
print(se) #結果為{33, 11, 22}
se.remove(22)
print(se) #結果為{33, 11}
se.discard(44)
# se.remove(44) #報錯
- set_name1.intersection(set_name2) 求兩集合的交集
se = {11,22,33,44}
be = {11,22,77,55}
ret = se.intersection(be)
print(ret) #結果為{11, 22}
- set_name1.union(set_name2) 求兩集合的并集,為新的集合
se = {11,22,33,44}
be = {11,22,77,55}
ret = se.union(be)
print(ret) #結果為{33, 11, 44, 77, 22, 55}
- set_name.pop() 不需要參數,隨機刪除一個
se = {11,22,33,44,4,4,5,1,5,2,8,4,9,6,5,65,2,5,2,58,2,58,2,8,52,8,6,654,487,4}
for i in range(10):ret = se.pop()print(ret)print(se,type(se))
- set_name1.update(set_name2) 取并集并附給name1
se = {11,22,33,44}
be = {11,22,77,55}
se.update(be)
print(se) #結果為{33, 11, 44, 77, 22, 55}
?
三元運算
- 格式:name = 值1 if 條件 else 值2
- 條件成立,就值1賦給name,否則把值2賦給name
- 可以這么說三元運算就是條件語句的簡化版
name = 12 if 2>3 else 25
print(name) #結果為25
name = 12 if 1==1 else 25
print(name) #結果為12
?
不同數據類型在內存的存址方式
- str(字符串) 一次性創建,不能修改,如果要修改必須重新創建
???
- list(列表) 存址方式為鏈表形式,元素之間記住了上一個元素的位置,下一個元素的位置
???
?
深淺拷貝
- 對于 數字 和 字符串 而言,賦值、淺拷貝和深拷貝無意義,因為其永遠指向同一個內存地址
import copy
str1 = 'alex'
str2 = str1 #賦值
str3 = copy.copy(str1) #淺拷貝
str4 = copy.deepcopy(str1) #深拷貝
print(id(str1),id(str2),id(str3),id(str4))
#結果為8373168 8373168 8373168 8373168
import copy
num1 = 1234
num2 = num1 #賦值
num3 = copy.copy(num1) #淺拷貝
num4 = copy.deepcopy(num1) #深拷貝
print(id(num1),id(num2),id(num3),id(num4))
#結果為1331088 1331088 1331088 1331088
- 對于字典、元祖、列表 而言,進行賦值、淺拷貝和深拷貝時,其內存地址的變化是不同的
import copy
dict1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
dict2 = dict1 #賦值
dict3 = copy.copy(dict1)
dict4 = copy.deepcopy(dict1)
print(id(dict1),id(dict2),id(dict3),id(dict4))
#結果為10077192 10077192 10505160 10464264
看到這結果,我們可以得出,賦值對于字典而言,其內存地址是沒有發生變化的,但是對淺拷貝和深拷貝的話,其內存地址都改變了,你可能會想,淺拷貝和深拷貝有啥區別了?
- 淺拷貝只拷貝第一層,深拷貝除了最后一層不拷貝,其他的都拷貝
淺拷貝:
import copy
dict1 = {"k1": "wu", "k2": 123, "k3": {'偶像':'景女神','人生格言':['景女神是最棒的','我們都是最棒的']}}
dict2 = copy.copy(dict1) #淺拷貝
# dict2['k1'] = 'jingliyang' #在第一層,dict1沒有跟著dict2變化
# print(dict1) #結果為{'k1': 'wu', 'k2': 123, 'k3': {'偶像': '景女神', '人生格言': ['景女神是最棒的', '我們都是最棒的']}}
# print(dict2) #結果為{'k1': 'jingliyang', 'k2': 123, 'k3': {'偶像': '景女神', '人生格言': ['景女神是最棒的', '我們都是最棒的']}}
dict2['k3']['人生格言'] = '每天很美好' #看到沒,在第二層,dict1賤賤的跟著dict2變化了
print(dict1) #結果為{'k2': 123, 'k3': {'人生格言': '每天很美好', '偶像': '景女神'}, 'k1': 'wu'}
print(dict2) #結果為{'k2': 123, 'k3': {'人生格言': '每天很美好', '偶像': '景女神'}, 'k1': 'wu'}
?
附圖:
深拷貝:
import copy
dict1 = {"k1": "wu", "k2": 123, "k3": {'偶像':'景女神','人生格言':['景女神是最棒的','我們都是最棒的']}}
dict2 = copy.deepcopy(dict1) #深拷貝
# dict2['k1'] = '景麗洋' #在這里改變第一層,dict1沒有跟著dict2變化
# print(dict1) #{'k3': {'人生格言': ['景女神是最棒的', '我們都是最棒的'], '偶像': '景女神'}, 'k1': 'wu', 'k2': 123}
# print(dict2) #{'k1': '景麗洋', 'k3': {'人生格言': ['景女神是最棒的', '我們都是最棒的'], '偶像': '景女神'}, 'k2': 123}
dict2['k3']['人生格言'] = '景女神,加油!' #你看,第二層dict1還是沒有跟著dict2變化
print(dict1) #{'k3': {'偶像': '景女神', '人生格言': ['景女神是最棒的', '我們都是最棒的']}, 'k1': 'wu', 'k2': 123}
print(dict2) #{'k3': {'偶像': '景女神', '人生格言': '景女神,加油!'}, 'k1': 'wu', 'k2': 123}
附圖:
?
函數
- 函數是面向過程編程,也叫函數式編程
- 當程序運行時,解釋器從上往下解釋,遇定義函數時先讀取到內存,但不執行
- 執行 --函數名()
- 語法結構:
def function_name(args):功能塊return 返回值
- return后面是返回值,不寫return,默認返回None,返回值是可以用變量接收的
- 在函數中,執行了return,函數后面的代碼就不執行了
為了理解更透徹,讓我們先看一個例子:
def add(x,y):z = x + yreturn zdef main():a = 12b = 13c = add(a,b)print(c)main()
print('End!')
首先這個例子中定義兩個函數,分別為add和main兩個函數,add函數有兩個形式參數x和y,而main函數無形參也無返回值,在執行main函數的過程中又去調用了add函數
發送郵件實例


復制代碼import smtplib from email.mime.text import MIMEText from email.utils import formataddrmsg = MIMEText('郵件內容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齊",'wptawy@126.com']) msg['To'] = formataddr(["走人",'424662508@qq.com']) msg['Subject'] = "主題"server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "郵箱密碼") server.sendmail('wptawy@126.com', ['424662508@qq.com',], msg.as_string()) server.quit()
?
局部變量和全局變量
- 局部變量,從字面上的意思理解就是肯定是生活在某個局部地方的,好!那在這里,定義在函數體內的變量叫做局部變量
- 全局變量,定義在函數體外的變量叫做全局變量
- 局部變量只可被本函數使用,全局變量可以被所有的語句訪問使用
- 由于局部變量定義在函數體內,故多個函數可以在各自函數體內使用相同的變量名作為自己的變量
看例子,我會找茬
def f1():x = 12print(x)def f2():y = 13print(y)def f3():print(x)print(y)def main():f1()f2()f3()main() print('End!')
是不是發現了錯誤呢?這就是函數內部調用其他的函數里的局部變量的錯誤
- 全局變量沒有定義在任何函數體內,如果在某個函數里修改某個全局變量,必須用global聲明一下這個變量是全局的才能修改
def printlocalx():x = 12print('f1 local x =',x)def printlocaly():y = 13print('f2 local y =',y)def readglobal():print('f3 read global x =',x)print('f3 read global y =',y)def modifyglobal():global xprint('f4 write x = -1')x = -1def main():printlocalx()printlocaly()readglobal()modifyglobal()x = 200
y = 100
main()
print('after modified global x =',x)
print('End')
結果為:f1 local x = 12f2 local y = 13f3 read global x = 200f3 read global y = 100f4 write x = -1after modified global x = -1End
- ?為了規范起見,全局變量建議用大寫,局部變量用小寫
?
形參和實參
- 在定義函數時的變量稱作函數的形參,作為外部值傳入函數的接口
- 函數調用時的變量稱作實參
def multi(x,y): #定義時的x,y就是形參z = x * yreturn zdef main():a = 12b = 13c = multi(a,b) #調用時的a,b就是實參print(c) main()
print('End')
?
位置參數和關鍵詞參數
- 按照函數定義時的位置順序傳入值的方式稱作位置參數傳入
- 按照函數定義時的關鍵詞對應關系傳入值的方式稱作關鍵詞參數傳入,這個也是老師說的指定參數
#梯形面積公式
def trapezoid_area(base_up,base_down,height):return 1/2*(base_up+base_down)*height
print(trapezoid_area(1,2,3)) #這種傳入參數的方式被稱作位置參數傳入
result = trapezoid_area(base_up=1,base_down=2,height=3)
#這種傳入參數的方式稱為關鍵詞參數傳入
print(result)
?
默認參數
- 默認參數就是在函數定義時給某個參數設定默認值,默認參數必須在普通參數之后
- 默認參數在不給其傳值時,使用默認值,給值就是修改默認值
def trapezoid_area(base_up,base_down,height=3):return 1/2*(base_up+base_down)*height
result1 = trapezoid_area(1,2) #傳入兩個參數也可,也可修改三參,即默認參數
print(result1)
你不知道的小秘密,你常用的print居然是一個既熟悉又陌生的人兒
print(' *',' ***',' *****',' |',sep='\n')
sep為print函數的默認參數,默認值為空格,傳入的\n為換行
?
動態參數
- def func(*args) 接受多個參數,內部自動構造元組
def f1(*a):print(a,type(a))f1(123) #結果為(123,) <class 'tuple'>#多傳幾個
f1(11,22,33) #結果為(11, 22, 33) <class 'tuple'>
你看,在定義函數的時候給參數前加了*,然后調用函數時輸出的結果為元組,那如果傳了列表呢?
def f1(*a):print(a,type(a))li = [11,22,33]
f1(li) #結果為([11, 22, 33],) <class 'tuple'>
結果是把列表當整體作為元素的元素了,那如果我們就是想要把列表的每個元素作為構造元組的元素呢?
def f1(*a):print(a,type(a))li = [11,22,33]
f1(*li) #結果為(11, 22, 33) <class 'tuple'>
其實只要在執行函數時傳入的參數前加*就可以了
?
- def func(**kwargs) 接收多個參數,內部自動構造字典
def f2(**b):print(b,type(b))f2(a1 = 123) #結果為{'a1': 123} <class 'dict'>
好,如果要給其傳入字典,而且也是要把每個鍵值對用于構造的字典的鍵值對,應該怎么做呢?相信很多人都想到了在前面加**吧?
def f2(**b):print(b,type(b))dict1 = {'k1':'景女神','k2':'景女神是最棒的'}
f2(**dict1) #結果為{'k2': '景女神是最棒的', 'k1': '景女神'} <class 'dict'>
另外,告訴你,如果傳入字典,你不加**,是會報錯的
?
- def func(*args,**kwargs):接受多個參數,既可以自動構造元組,又可以自動構造字典,而且一個*的必須在兩個*的前面
def f3(*args,**kwargs):print(args,type(args))print(kwargs,type(kwargs))f3(11,22,33,k1=123,k2=456)
結果為:(11, 22, 33) <class 'tuple'>{'k1': 123, 'k2': 456} <class 'dict'>
你看程序能自動識別構造元素和字典,這樣就可以實現給函數傳入多個參數了
?
??????????????????????????????????????????????????????? 歡迎大家對我的博客內容提出質疑和提問!謝謝
????????????????? 筆者:拍省先生