随笔 - 60  文章 - 2 评论 - 0 trackbacks - 0

p154-
#callable(对象)
#对象()能不能运行,就是callable() 要做的事情
#1
class A:
    pass
a = A()
print(callable(a)) #False 不可调用
#2
class B:
    def __call__(self, *args, **kwargs):
        print('B')
b = B()
print(callable(b)) #True 判断一个对象是否能callable ,
b() #B #既然可以callable 那么可以加括号 b() 调用的是B类内部的__call__ 方法
#Flask框架用到__call__
#__len__ 类内的数量函数,返回类内某个指定属性的数量
class Grade:
    def __init__(self,name):
        self.name = name
        self.student = []

grade1 = Grade('三年级三班')
grade1.student.append('tom')
grade1.student.append('jerry')
print(len(grade1.student)) #2
#如果我想直接len(grade1) 返回2 呢?
#可以在Grade类里添加一个__len__ 方法,定义好方法以后,外部直接用去掉下划线的方法名加括号对象的方式调用,效果等价于“对象.__len__()”
class Grade:
    def __init__(self,name):
        self.name = name
        self.student = []
    def __len__(self):
        return len(self.student)
grade1 = Grade('三年级三班')
grade1.student.append('tom')
grade1.student.append('jerry')
print(len(grade1)) #2
#__new__
#先看执行结果
#1
class Person :
    def __new__(cls, *args, **kwargs):
        print('new')

    def __init__(self):
        print('init')
Person() # new
##2
class Person :
    def __new__(cls, *args, **kwargs):
        print('new')
        return super().__new__(cls)

    def __init__(self):
        print('init')
Person() # 先打印new 再打印init
#在之前涉及的,类的实例化过程,先创建一个内存空间,空间里装了类指针,这里的创建空间是由__new__来完成的
#所以在实例化的时候先调用new 再调用init
#还可以变更为:
class Person :
    def __new__(cls, *args, **kwargs):
        obj = super().__new__(cls)
        print('new',obj) #return new <__main__.Person object at 0x02BCE070>
        return obj

    def __init__(self):
        print('init',self) #return new <__main__.Person object at 0x02BCE070>
Person() #2个print返回地址一样,其实是先执行new ,返回的obj 给了init
#设计模式 - 单例模式
#一个类 从头到尾 只会创建一次self的空间
class Tom:
    def __new__(cls, *args, **kwargs):
        obj = super().__new__(cls)
        return obj
    def __init__(self,cloth,shoe): #tom的衣服和鞋子
        self.cloth = cloth
        self.shoe = shoe
t1 = Tom('Nike','Adidas')
t2 = Tom('Anta','Lining')
print(t1.cloth) #Nike
print(t2.cloth) #Anta
#Tom这个人是唯一的,只能做一次实例化可以做如下变更,定义一个类私有变量,在new中判断是否实例化过
class Tom:
    __instance = None #创建一个私有变量
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None: #判断如果为空就创建
            cls.__instance = super().__new__(cls)
        return cls.__instance
    def __init__(self,cloth,shoe): #tom的衣服和鞋子
        self.cloth = cloth
        self.shoe = shoe

t1 = Tom('Nike','Adidas')
t2 = Tom('Anta','Lining')
print(t1.cloth,t1) #Anta <__main__.Tom object at 0x02E302F8>
print(t2.cloth,t2) #Anta <__main__.Tom object at 0x02E302F8> #这里t1 和t2 返回的地址是一样的
#python中有更简单的 单例模式
#from 模块名 import 实例化的对象  ,比如我要用到t1 这个对象,我可以在别的模块中引用这个模块里的t1
#__str__ __repr__
#例子
class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
c1 = Course('python',100,5)
c2 = Course('c++',200,5)
print(c1) #<__main__.Course object at 0x019CF580>  这里打印的是一个地址
print(f'{c1.name}课程,周期是{c1.period},价格是{c1.price}元。') #python课程,周期是5,价格是100元。
print(f'{c2.name}课程,周期是{c2.period},价格是{c2.price}元。') #python课程,周期是5,价格是100元。
#这里打印太复杂,可以在类中直接实现一个__str__方法
class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
    def __str__(self):
        return ','.join([self.name,str(self.price),str(self.period)])
c1 = Course('python',100,5)
c2 = Course('c++',200,5)
print(c1) #python,100,5  #这里打印对象名 就是打印了对象的属性 __str__内返回什么,就打印什么 【必须返回字符串格式】
#例子
class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
    def __repr__(self):
        return self.name
c1 = Course('python',100,5)
print(c1) #python repr 跟str 一样功能

#如果repr 和str 都在类里定义了呢?
class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period
    def __repr__(self):
        return self.name
    def __str__(self):
        return 'aaa'
c1 = Course('python',100,5)
print(c1) #aaa 返回的是str返回的内容,当repr 和str 都定义了,打印对象print(对象),返回结果是str方法的记录
print('%r'%c1) #python 当打印的字符串是用%r 和 对象c1拼接的时候,调用的是repr方法,直接打印c1,print(c1)等价于print('%s'%c1)

#了解网络的基础知识
#了解底层的网络通信
#网络的概念
#基于原生的网络模块来实现通信
#完成一些简单的程序
#了解一些协议的特点,扬长避短,什么时候用,什么时候不用

#概念
#mac地址和ip地址,mac地址唯一,ip不唯一
#局域网,连在同一个交换机上的多台机器形成局域网 ,交换机只认识mac地址
#交换机广播,交换机单播(只发给指定的机器),交换机组播(给一部分发信息)
#arp协议(地址解析协议):通过一台机器的ip地址获取到它的mac地址的协议,用到了交换机的广播和单播
#局域网之间的通信用路由器,网关,路由器可以理解ip地址

#判断192.168.12.1 和 192.168.13.1 是否在同一个局域网里,要判断子网掩码
# 子网掩码和ip地址分别转化成2进制,然后按位与操作,得到的结果相等,即是同一个网段
#比如两者的子网掩码都是255.255.255.0  转成2进制是 11111111 11111111 11111111 00000000
#子网掩码2进制           与192.168.12.1  的2进制11000000 10101000 00001100 00000001
# 按位与得到 11000000 10101000 00001100 00000000  = 192.168.12.0
# 192.168.13.1 与它的子网掩码255.255.255.0 按位与得到 192.168.13.0
#得到结果不一致,不是同一个网段,如果子网掩码都是255.255.0.0 ,按位与后得到的结果都是192.168.0.0, 那么就是同一个网段

#socket 实现C/S结构程序
#server.py 服务器端
import socket
sk = socket.socket() #实例化
sk.bind(('127.0.0.1',22000)) #绑定地址
sk.listen() #监听
obj,addr = sk.accept() #获取连接,连接是个套接字
obj.send(b'hello') #用这个套接字 发送内容
content = obj.recv(1024) #用这个套接字 接受内容
print(content) #打印
sk.close() #关闭

#client.py 客户端
import socket
sk = socket.socket() #实例化socket对象
sk.connect(('127.0.0.1',22000)) #生成连接
content = sk.recv(1023) #接受内容
print(content) #打印内容
sk.send(b'bye') #发送内容
sk.close() #关闭


#OSI七层结构(或者五层结构)
#应用层,表示层,会话层 (合成一层:应用层) :存放python等语言的代码
#传输层 : 跟端口有关 tcp udp 协议
#网络层:跟ip地址有关,路由器
#数据链路层 :跟mac地址有关,交换机
#物理层 :底层,转换成电路信号
posted on 2020-08-05 18:07  94小渣渣  阅读(16)  评论(0编辑  收藏