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

猜你喜欢

转载自blog.csdn.net/qq_33060225/article/details/83989216