1. 程式人生 > >老男孩14期自動化運維day7隨筆和作業

老男孩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()