python study day07

面向对象高级语法部分

经典类vs新式类

1 、静态方法、类方法、属性方法

1.1静态方法 @staticmethod

只是名义上归类管理,实际上在静态方法里访问不了类或实例中的类的任何方法

通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,其变为普通的方法,可以在实例化后直接调用,并且在方法里可以通过self,调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没有什么关系了,它唯一的关联就是需要通过类名来调用这个方法。
在这里插入图片描述
在这里插入图片描述

1.2类方法 @classmethod

只能访问类变量,不能访问实例变量

在这里插入图片描述
出错
在这里插入图片描述
可以访问

1.3属性方法 @property

把一个方法变成一个静态属性
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3.1删除

在这里插入图片描述
1处是修改
2处是删除

1.3.2用途

以后你就会需要很多场景是不能简单通过定义静态属性来实现的,比如,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是飞走了。想知道这种状态你必须经历以下几步:
1、连接航空公司API
2、对查询结果进行解析
3、返回结果给你的用户
因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回结果,但是这些动作过程不需要用户关心,用户只需要调用这个属性就可以

 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...please check later")

    @flight_status.setter #修改
    def flight_status(self,status):
        status_dic = {
            0:"canceled",
            1:"arrived",
            2:"departured"
        }
        print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status))

    @flight_status.deleter  #删除
    def flight_status(self):
        print("status got removed...")

f= Flight("CA980")
f.flight_status
f.flight_status =  2 #触发@flight_status.setter
del f.flight_status #触发@flight_status.deleter


2、类的特殊方法

2.1__doc__ 表示类的描述信息

在这里插入图片描述

2.2_module_ 和 _class _

___module _表示当前操作的对象在那个模块
_class _ 表示当前操作的对象的类是什么
在这里插入图片描述

2.3_init__ 构造方法,通过类创建对象时,自动触发执行。

2.4 _del_析构方法 当对象在内存中被释放时,自动触发执行

注:此方法一般无需定义,因为python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

2.5 _call_对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象= 类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象() 或者类()()
在这里插入图片描述

class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo()     #执行__init__
obj()   #执行__call__

还可以传入参数
在这里插入图片描述

class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print('__call__',args,kwargs)

obj = Foo()     #执行__init__
obj(124,name=24)   #执行__call__

如何判断一个对象能是否能被调用,可以用callable()函数,若能被调用,则返回Ture

print(callable(obj))

结果:True

2.6__dict__ 查看类或对象中的所有成员

通过类调用,打印类中的所有属性,不包括实例属性
通过对象调用,打印所有的实例属性,不包括类属性

在这里插入图片描述

2.7 __ str__

如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。
在这里插入图片描述
在这里插入图片描述

2.8__getitem__ setitem delitem

用于索引操作,如字典。以上分别表示获取、设置、删除数据
可以用于自己封装一个字典
在这里插入图片描述
在这里插入图片描述

class Foo(object):
    def __init__(self):
        self.name ={}

    def __getitem__(self, item):
        print('__getitem__',item)

    def __setitem__(self, key, value):

        print('__setitem__',key,value)
        self.name[key] = value


    def __delitem__(self, key):
        print('__delitem__',key)

obj = Foo()
result = obj['K1']
obj['k2'] = 'alex'
print(obj.name)
del obj['k1']

2.9__new__ __ metaclass__

class Foo(object):

    def __init__(self,name):
        self.name = name


f = Foo('alex')

上述代码中,obj是通过Foo类实例化的对象,其实,不仅obj是一个对象,Foo类本身也是一个对象,因为python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的构造方法创建。
在这里插入图片描述
所以,f对象是Foo类的一个实例,Foo类对象是type类的一个实例,即:Foo类对象是通过type类的构造方法创建。

2.9.1 类的两种创建方式

在这里插入图片描述
a)普通类

class Foo(object):

    def func(self):
        print("hello aliex")

b)特殊方式

def func(self):
    print("hello alex")

Foo = type('Foo',(object,),{'func':func})

type 第一个参数:类名
type 第二个参数:当前类的基类(元组)
type第三个参数:类的成员

带有初始化函数的:

def func(self):
    print("hello alex")
    
def __init__(self,name,age):
    self.name = name
    self.age = age

Foo = type('Foo',(object,),{'func':func,'__init__':__init__})

f= Foo('jack',22)

类是由type类实例化产生的

类默认是由type类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 metaclasss,其用来表示该类由谁来实例化创建,所以,我们可以为__mataclass__设置有个type类的派生类,从而查看类的创建的过程

__ new__()函数执行先于__init__()函数,其中__new__()函数是用来创建实例的,可以不写(大多数不用写)若是写的话,也就是重构的__new__()函数,需要继承父类的这个函数的

在这里插入图片描述

class MyType(type):
    def __init__(self,*args,**kwargs):

        print("Mytype __init__",*args,**kwargs)

    def __call__(self, *args, **kwargs):
        print("Mytype __call__", *args, **kwargs)
        obj = self.__new__(self)
        print("obj ",obj,*args, **kwargs)
        print(self)
        self.__init__(obj,*args, **kwargs)
        return obj

    def __new__(cls, *args, **kwargs):
        print("Mytype __new__",*args,**kwargs)
        return type.__new__(cls, *args, **kwargs)

print('here...')


class Foo(obj ect,metaclass=MyType):


    def __init__(self,name):
        self.name = name

        print("Foo __init__")

    def __new__(cls, *args, **kwargs):
        print("Foo __new__",cls, *args, **kwargs)
        return object.__new__(cls)	#去继承父类的__new__()函数,必须是返回

f = Foo("Alex")
print("f",f)
print("fname",f.name)

此代码执行过程
其中__new__()函数 是被(MyType)__ call__()函数调用执行的

在这里插入图片描述
在这里插入图片描述

3、反射

hasattr(obj,name_str) ,判断一个对象里是否有对应的name_str字符串的方法,有的话返回True
getattr(obj,name_str),根据字符串去获取obj对象里的对应的方法的内存地址
setattr(obj,’y’,z),is equivalent to x.y=z
delattr(obj,name_str),删掉对象里的name_str字符串的方法或者属性

class Foo(object):
    def __init__(self):
        self.name = 'alex'

    def func(self):
        return 'func'


obj = Foo()

# #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func')

# #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func')

# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)

# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')

可以实现内存的动态分配:
在这里插入图片描述

4、异常处理

结构:
	try:
		data
	except (Error1,Error2) as e:
		pass
	except Exception as e:	#抓所有错误 ,不建议开始使用,用在最后,表示未知错误


在这里插入图片描述

data = {}
try:
    data["name"]

except KeyError as e:
    print("没有这个key",e)

except KeyError as e: 这个e是获取错误的信息

name=[1,2]
data = {}
try:
    name[3]
    data["name"]

except (KeyError,IndexError) as e:
    print("没有这个key",e)

name=[1,2]
data = {}
try:
    name[3]
    data["name"]

except KeyError as e:
    print("没有这个key",e)

except IndexError as e:
    print("列表",e)

except Exception as e:
    print("出现未知错误",e)

else:
    print("一切正常")

finally:
    print("不管有没有错,都执行")


4.1常见的错误类型

1) AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
2)IOError 输入/输出异常;基本上是无法打开文件
3)ImportError 无法引入模块或包;基本上是路径问题或名称错误
4)IndentationError 语法错误(的子类) ;代码没有正确对齐
5)IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
6)KeyError 试图访问字典里不存在的键
7)KeyboardInterrupt Ctrl+C被按下
8)NameError 使用一个还未被赋予对象的变量
9)SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
10)TypeError 传入对象类型与要求的不符合
11)UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
12)ValueError 传入一个调用者不期望的值,即使值的类型是正确的

4.2自己定义异常

class AlexException(Exception):
    def __init__(self,name):
        self.name =name

    #def __str__(self):
       #return self.name



try:
    raise AlexException("数据库连不上")

except AlexException as e:
    print(e)

4.3 断言

assert

在这里插入图片描述

5、 Socket开发基础

5.1计算机之间的通信

OSI七层模式:物理层、数据链路层(mac)、网络层(IP)、传输层、会话层、表示层、应用层。
通信协议:TCP/IP(三次握手,四次断开) UDP
所有协议的数据的收和发都是通过socket,socket可以实现两种通信协议
在这里插入图片描述

5.2 TCP/IP通信过程

IP;计算机的IP地址
PORT:一个计算机上最多有65535个端口
伪代码
在这里插入图片描述

5.3 Socket概念:

Socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递。我们知道网络通信都是基于IP+PORT方能定位到目标的具体机器上的具体服务,操作系统有0-65535个端口,每个端口都可以独立对外提供服务,如果,把一个公司比作一台电脑,那么公司的总机号码就相当于IP地址,每个员工的分机号就相当于端口,你想找公司某个人,必须先打电话到总机,然后再转分机。
建立一个socket必须至少有2端,一个服务端,一个客户端,服务端被动等待并接收请求,客户端主动发起请求,连接建立之后,双方可以互发数据。

服务端:
1)声明socket实例Server = socket.socket(AF.INET,SOCK.SOCK_STREAM)
2)绑定端口 server.blind()
3)监听 server.listen()
while True:
4)阻塞 conn,addr = server.accept() 接进来创建一个实例
While True:
print(“new conn”,addr)
data = conn.recv(1024) #官方建议最大 #recv默认是阻塞的
if not data:
break #客户端已断开
print(data)
conn.send(data.upper())
客户端
1)实例化client = socket.socket(AF.INET,SOCK.SOCK_STREAM
2)连接 client.connect(serverip,9999)
3)发数据 client.send(data)
在这里插入图片描述

5.4 socket Families(地址簇)

socket.AF_UNIX  unix本机进程间通信
socket.AF_INET  IPV4
socket.AF_INET6  IPV6

5.5 socket Types

socket.SOCK_STREAM	#for tcp协议
socket.SOCK_DGRAM	#for udp协议
socket.SOCK_RAW		#原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以,其次,SOCK_RAW也可以处理特殊的IPv4报文,此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
Socket.SOCK_RDM		#是一种可靠的UDP形式,即保证交付数据,但不保证顺序。SOCK_RDM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.SOCK_SEQPACKET		#废弃了

5.6 socket 通信

Socket通信时,数据的传输必须是byte类型,并且不能发送空,recv是有默认的接收大小
Server端

import socket

server = socket.socket()    #声明socket类型,同时生成socket连接对象
server.bind(('localhost',6969))  #绑定要监听端口
server.listen()#监听

print("start wait")
conn,addr =server.accept()#等电话打进来   conn是一个接进来的客户端,在服务器端为其生成的一个实例,addr表示地址
print("accept wait")

data = conn.recv(1024)
print('recv:',data)

conn.send(data.upper())


server.close()

客户端

import socket

client = socket.socket()    #声明socket类型,同时生成socket连接对象
client.connect(('localhost',6969))

client.send(b"hello word!")
data = client.recv(1024)
print("recy:",data)
client.close()

排队通信

Socket端

import socket
server = socket.socket()    #声明socket类型,同时生成socket连接对象
server.bind(('localhost',6969))  #绑定要监听端口
server.listen(5)#监听

print("start wait")

while True:
    conn,addr =server.accept()#等电话打进来   conn是一个接进来的客户端,在服务器端为其生成的一个实例,addr表示地址
    print("accept wait")
    while True:
        try :
            data = conn.recv(1024)
            print('recv:',data.decode())
            conn.send(data.upper())
        except ConnectionResetError:
            break
server.close()

client端:

import socket

client = socket.socket()    #声明socket类型,同时生成socket连接对象
client.connect(('localhost',6969))

while True:
    message = input(">>:")
    client.send(message.encode('utf-8'))
    data = client.recv(1024)
    print("recy:",data.decode())

client.close()

6、动态导入模块

解释器自己用的

lib = __import__("lib.aa")      #导入的是lib

obj = lib.aa.C()


官方建议:

import importlib
aa = importlib.import_module('lib.aa')  #官方建议
print(aa.C().name)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值