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()