老男孩14期自動化運維day7隨筆和作業
1.static_method,class_method,property_method方法
(1)static_method 靜態方法
靜態方法:實際上跟類沒有什麼關係,相當於是類下的一個函式,與類沒有關係(很少用),只是名義上歸類管理,實際上在靜態方法裡訪問不了類或例項中的任何屬性(比如說python的sys模組,相當於是很多方法的集合類似於工具包,其中在sys類中各種方法都是使用的靜態方法)
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
class Dog(object):
def __init__(self, name):
self.name=name
@staticmethod # 靜態方法:實際上跟類沒什麼關係了,相當於是類下的一個函式,與類沒有關係(很少用)
# def eat(self,food):
# print("%s is eating %s "%(self.name,food))
def eat():
print("is eat")
d=Dog("A")
d.eat()
# 靜態方法
# 只是名義上歸類管理,實際上在靜態方法裡訪問不了類或實力中的任何屬性
(2)class_method 類方法
類方法:只能訪問類變數,不能訪問例項變數(很少用)
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
class Dog(object):
n=123 # 類變數
def __init__(self,name):
self.name=name
@classmethod # 類方法 很少用
def eat(self):
print("%s is eating %s "%(self.n,'baozi'))
d=Dog("A")
d.eat()
# 類方法
# 只能訪問類方法,不能訪問例項變數
執行結果為 123 is eating baozi
(3)property_method 屬性方法(有時候用)
屬性方法:把一個方法變成一個靜態屬性,作用為隱藏實現細節,比如攜程網需要調機場航班狀態的介面,暴露給使用者,使用者只需要調屬性(實際上是方法變成了屬性,調的還是方法),而不用去帶入引數或者關心實現細節。
以下為propert_method 簡單例子
class Dog(object):
def __init__(self,name):
self.name=name
@property # (有時候用)
def eat(self):
print("%s is eating %s "%(self.name,'baozi'))
@eat.setter # 修改屬性
def eat(self, food):
print("set to food:", food)
@eat.deleter # 刪除屬性
def eat(self):
del self.name
print("刪完了")
d=Dog("A")
d.eat
d.eat="包子"
# 屬性方法刪不了,必須定義方法刪
# del d.eat
# print(d.eat)
del d.eat
# 屬性方法
# 把一個方法變成一個靜態屬性
# 隱藏實現細節
以下為攜程調飛機航班狀態介面的簡化例子:
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
class Flight(object):
def __init__(self,name):
self.flight_name=name
def checking_status(self):
print("checking flight %s status "% self.flight_name)
return 1
@property
def flight_status(self):
status = self.checking_status()
if status == 0:
print("flight got canceled..")
elif status == 1:
print("flight is arrived..")
elif status == 2:
print("flight has departured already..")
else:
print("cannot confirm the flight status...")
@flight_status.setter
def flight_status(self,status):
print("%s has changed to %s"%(self.flight_name,status))
f=Flight("A389")
f.flight_status
f.flight_status="2"
# 隱藏實現細節
2.類的特殊成員方法
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
from lib import aa
class Foo:
''' 類的描述'''
def func(self):
pass
def __call__(self, *args, **kwargs): # 可以使物件後面加括號,觸發執行
print(1,args,kwargs)
def __str__(self): # 可以使列印例項時返回值(沒有這個方法時,print(d)是例項的記憶體地址)
return "aaaa"
def __getitem__(self, key):
print('__getitem___',key)
def __setitem__(self, key, value): # 把一個例項變成字典
print('__setitem__',key,value)
def __delitem__(self, key):
print('__delitem__',key)
obj=aa.A()
print(Foo.__doc__) # 列印類前面的註釋(就是類是幹嘛用的)
print(obj.__module__) # 表示當前物件在哪個模組 輸出模組
print(obj.__class__) # 表示當前物件在哪個類 輸出類
d=Foo()
d(1,2,k=3)
print(Foo.__dict__) # 檢視類中所有方法和成員,以字典形式列印
print(d.__dict__) # 檢視例項中的所有變數,以字典形式列印
print(d)
d['name']="A"
print(d['name'])
3.建立類的兩種方法
一切皆物件,類穿建立例項,而type類負責建立類,建立的類是type類的一個例項
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
# class Foo(object): # 建立類的普通方式
# def __init__(self,name):
# self.name=name
# f=Foo("A")
def func(self): # 建立類的特殊方式
print("hello %s"%self.name)
def __init__(self,name,age):
self.name=name
self.age=age
Foo=type('Foo',(object,),{'func':func,'__init__':__init__})
f=Foo("A",22)
f.func()
# 一切皆物件 f,Foo都是物件。f通過Foo類的構造方法建立,那麼Foo類也是有某個類的構造方法建立(或者Foo類是type類例項化的)
print(type(f))
print(type(Foo)) # 列印結果為 <class 'type'> Foo類後面的類就是type,Foo類是type類的一個例項
如上:一切皆物件 f,Foo都是物件。f通過Foo類的構造方法建立,那麼Foo類也是有某個類的構造方法建立(或者Foo類是type類例項化的)
print(type(Foo)) # 列印結果為 <class ‘type’> Foo類後面的類就是type,Foo類是type類的一個例項
4.metaclass
__ new __ 是用來建立例項的 預設父類有new方法
兩個階段:
第一階段:直譯器從上到下執行程式碼建立Foo類
第二階段:通過Foo類建立obj物件
__author__ = "Alex Li"
class MyType(type):
def __init__(self, what, bases=None, dict=None):
print("--MyType init---")
super(MyType, self).__init__(what, bases, dict)
def __call__(self, *args, **kwargs):
print("--MyType call---")
obj = self.__new__(self, *args, **kwargs)
obj.data = {"name":111}
self.__init__(obj, *args, **kwargs)
class Foo(object):
__metaclass__ = MyType
def __init__(self, name):
self.name = name
print("Foo ---init__")
def __new__(cls, *args, **kwargs):
print("Foo --new--")
# print(object.__new__(cls)) # new是用來建立例項的 預設父類有new方法 (這裡把new重構了,所以要return object.__new__(cls))
# cls相當於foo
return object.__new__(cls) # 繼承父親的__new__方法
# 第一階段:直譯器從上到下執行程式碼建立Foo類
# 第二階段:通過Foo類建立obj物件
obj = Foo("Alex")
print(obj.name)
5.反射(重要)
反射 就是把字串對映到函式的記憶體地址
比如使用者輸入一個字串,能夠實現去某個類中呼叫與該字元串同名的方法
hasattr(obj,name_str),判斷一個物件裡是否有對應的name_str字串的方法 返回true or false
getattr(obj,name_str),根據字串去獲取obj物件裡的對應的方法的記憶體地址
setattr(obj,name_str,value),根據字串去設定方法
delattr (obj,name_str),根據字串刪除方法
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
def bulk(self):
print("%s is yelling..."%self.name)
class Dog(object):
def __init__(self,name):
self.name=name
def eat(self,food):
print("%s is eating %s"%(self.name,food))
d = Dog("A")
choice = input(">>:").strip()
# print(hasattr(d,choice))
# print(getattr(d,choice))
if hasattr(d,choice):
func = getattr(d,choice)
func("banana")
# delattr(d,choice)
else:
setattr(d,choice,bulk) # d.talk=bulk bulk本身在類外 把bulk的記憶體地址賦給d.talk 使d.talk有bulk的功能
d.talk(d)
# 反射 就是把字串對映到函式的記憶體地址
# hasattr(obj,name_str),判斷一個物件裡是否有對應的name_str字串的方法 返回true or false
# getattr(obj,name_str),根據字串去獲取obj物件裡的對應的方法的記憶體地址
# setattr(obj,name_str,value),根據字串去設定方法
# delattr (obj,name_str),根據字串刪除方法
6.異常處理
python 2.x except Exception,e /except Exception as e
python 3.x except Exception as e
except Exception as e:抓住所有錯誤, 一般放到最後,但是列如indentation等語法縮排錯誤,是在編譯器編譯的時候就會報錯,所以程式並不能執行起來,所以抓不到indetation等縮排錯誤,另外語法錯誤也抓不到
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
data={}
names=[1,2,3]
try:
a=1
print(a)
# names[3]
# data['name']
#open("1.txt") # python 2.x是IOError 3.x是FileNotfounderror
except (KeyError,IndexError) as e: # 2.7是 except Exception,e
print("沒有Key",e)
except IndexError as e:
print("列表操作錯誤",e)
except Exception as e: # 抓住所有錯誤 一般放到最後 # indentation error 縮排,語法錯誤抓不到
print("出錯了",e)
else:
print("一切正常")
finally: # 不管有沒有錯都執行
print("不管有沒有錯都執行")
自定義異常
使用 raise YourException raise 關鍵字,定義YourException類時候是繼承Exception類的
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
class YangException(Exception):
def __init__(self,msg):
self.message=msg
# def __str__(self):
# return self.message
try:
raise YangException("我的異常")
except Exception as e:
print(e)
7.socket 通訊
OSI網路七層架構中,
應用層
表示層
會話層
傳輸層
網路層
資料鏈路層
物理層
TCP/IP 協議三次握手,四次斷開
1.syn
2.ack+syn
3.ack
傳輸層中,tcp/ip協議將底層的socket通訊封裝了。
socket叫做套接字,可以實現不同主機間的通訊,程序間的通訊(程序有程序鎖,只能通過建立socket連線來進行通訊)
socket:[本地主機,埠]<—>[目標主機,埠]
地址簇:在宣告socket型別時要宣告在網路層的地址簇,例如AF_INET(IPV4),AF_INET6 (IPV 6,AF_UNIX等
socket 協議型別(socket protocol type):
socket.SOCK_STREAM 流式socket for TCP(預設)
socket.SOCK_DGRAM 資料報式socket for UDP
socket.SOCK_RAW 偽造IP地址,發動DDOS洪水攻擊的方式
在宣告socket型別時,同時生成socket連線物件。
socket能夠傳輸字串,二進位制等資料。
在python2.x 中只能傳字串
在python3.x 中只能傳二進位制
服務端
server=socket.socket(AF.INET,socket.SOCK_STREAM) # 預設不寫
server.bind((localhost,9999)) # 是一個元組形式
server.listen()
conn,addr=server.accpet() # 阻塞 每進來一個連線 給一個conn例項而不是server
while True:
print(“new conn”,addr)
data=conn.recv(1024) #官方建議 不超過8192 (8k) recv 預設是阻塞的
…
客戶端
client=socket.socket(AF.INET,socket.SOCK_STREAM) # 預設不寫
client.connect((serverip,9999))
client.send(data)
client.recv(dat)
…
以下為一個多連線socket通訊(一個連線上,斷了之後,可以連線兩一個)
使用while true 死迴圈的方式,讓server在失去client的時候不會自動掛掉,進而等待下一個連線,recv()是有大小限制的,在server端呼叫listen(int)方法中引數是監聽的最多會話個數,即等待的個數。
使用socket通訊能夠傳輸linux命令,伺服器端接收命令的字串後呼叫popen(str)來執行命令,呼叫read()將命令執行的結果讀出來並顯示。比如 data=popen(str).read() str 是客戶端發過來的執行命令的字串格式,data是在伺服器端執行完命令後結果的展示。
在傳送資料的時候,send方法時有大小限制的,send大小是取決於不同作業系統的緩衝去大小。
server:
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
# 伺服器端 實現 簡單多連線socket通訊,一個結束通話,另一個連上
import socket
server=socket.socket()
server.bind(('localhost',6969)) # 繫結要監聽的埠
server.listen(5) # 監聽(最多可監聽5個對話,相當於可以有五個連線排隊)
print("i'm waiting for calling..")
while True:
conn,addr=server.accept() # 等待訊息
print(conn, addr) # conn連線物件
# conn就是客戶端連過來而在伺服器端為其生成的一個連線例項
print("it's comming")
while True:
data=conn.recv(1024)
print("recv:",data)
if not data:# 如果data為空
print("client has lost....")
break
conn.send(data.upper())# 變大寫
# send是取決於不同系統的緩衝區大小
server.close()
client:
#!/usr/bin/env python
# coding:utf-8
# Author:Yang
# 客戶端
import socket
client=socket.socket() # 預設地址簇為 AF_INET (IPV4) 宣告socket型別,同事生成socket連線物件
client.connect(('localhost',6969))
while True:
msg=input(">>:").strip()
if len(msg)==0:continue# 不能send None
client.send(msg.encode("utf-8")) # python2.x 都是字串 python3.x都是二進位制
data=client.recv(1024) # recv大小是有限制的
print("recv:",data)
client.close()