1.拷贝、浅复制和深复制
from copy import copy, deepcopy
class Dog:
def __init__(self, name, color='黑色'):
self.name = name
self.color = color
class Person:
def __init__(self, name, age=0, gender='女'):
self.name = name
self.age = age
self.gender = gender
self.dog = None
def __repr__(self):
return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'
p1 = Person('小明')
print(p1) # <'name': '小明', 'age': 0, 'gender': '女', 'dog': None, id:35399624>
1.1 直接赋值
p2 = p1
print(p2) # <'name': '小明', 'age': 0, 'gender': '女', 'dog': None, id:32036936>
p2.name = '小花'
print(p2) # <'name': '小花', 'age': 0, 'gender': '女', 'dog': None, id:32036936>
print(p1) # <'name': '小花', 'age': 0, 'gender': '女', 'dog': None, id:32036936>
1.2 拷贝
不管怎么拷贝,都是复制原数据产生一个新的数据并且将新数据的地址返回
p1 = Person('小明')
print('p1:', p1) # p1: <'name': '小明', 'age': 0, 'gender': '女', 'dog': None, id:35314312>
p3 = copy(p1)
p4 = deepcopy(p1)
print('p3:', p3) # p3: <'name': '小明', 'age': 0, 'gender': '女', 'dog': None, id:35320904>
print('p4:', p4) # p4: <'name': '小明', 'age': 0, 'gender': '女', 'dog': None, id:35321096>
1.3 浅拷贝和深拷贝的区别
总结:
-
**直接赋值:**其实就是对象的引用(别名)。
-
**浅拷贝(copy):**拷贝父对象,不会拷贝对象的内部的子对象。
-
深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
1. 浅拷贝
copy模块里面的copy方法实现。浅拷贝后,改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;改变原始对象中为不可变类型的元素的值,不会响拷贝对象。
2. 深拷贝
copy模块里面的deepcopy方法实现。深拷贝,除了顶层拷贝,还对子元素也进行了拷贝。经过深拷贝后,原始对象和拷贝对象所有的可变元素地址都没有相同的了。
print('=================浅拷贝=================')
p1 = Person('Tom', 18, '男')
p1.dog = Dog('大黄', '黄色')
print('p1:', p1) # p1: <'name': 'Tom', 'age': 18, 'gender': '男', 'dog': <__main__.Dog object at 0x00000000021DDD08>, id:35518152>
# 浅拷贝
p2 = copy(p1)
print('p2:', p2) # p2: <'name': 'Tom', 'age': 18, 'gender': '男', 'dog': <__main__.Dog object at 0x00000000021DDD08>, id:35683208>
p2.dog.color = '绿色'
print(p1.dog.color) # 绿色
print('================深拷贝====================')
p1 = Person('Tom', 18, '男')
p1.dog = Dog('大黄', '黄色')
print('p1:', p1) # p1: <'name': 'Tom', 'age': 18, 'gender': '男', 'dog': <__main__.Dog object at 0x00000000027E27C8>, id:41917640>
# 深拷贝
p2 = deepcopy(p1)
print('p2:', p2) # p2: <'name': 'Tom', 'age': 18, 'gender': '男', 'dog': <__main__.Dog object at 0x0000000002806C88>, id:41970376>
p2.dog.color = '绿色'
print(p1.dog.color) # 黄色
2.内存管理
-
内存管理:
python内存管理是自动化(指的是对堆上的内存进行管理)
-
内存的开辟
只要需要保存数据的时候系统就会自动在堆上开辟内存空间保存数据。
注意:如果需要被保存的数据是数字或者字符串,系统会先检查专门保存数字字符串的的缓存区中是否已经存在这
个数据,如果存在直接返回之前的数据的地址,不存在才会开辟新的内存去保存。(短小数字和字符串)
str1 = 'abc'
list1 = ['abc', 10, 20]
print(id(str1), id(list1[0])) # 4468066352 4468066352
list2 = []
list3 = []
print(id(list2), id(list3)) # 4467411936 4468530144
num1 = -6
num2 = -6
print(id(-6), id(-6)) # 31630224 31630224
- 内存的释放(垃圾回收)
Python中的每一个数据都有一个属性用来保存这个数据的引用个数(引用计数),当引用计数的值为0,那么这个数据就会自动销毁。实际上会有短暂的延迟,人感觉不到。
3.服务端Server
# 1.socket
# socket又叫套接字(实现通信的两个端(程序)就是套接字)
# 套接字有两种:服务器套接字(server)、客户端套接字(client)
# 2.服务器套接字
# 1)创建socket对象(买电话机)
from socket import socket
"""
socket(family=AF_INET, type=SOCK_STREAM) - 创建一个套接字对象
family - IP的类型(ipv4, ipv6);
AF_INET == ipv4 (默认的)
AF_INET6 == ipv6
type - 传输类型(TCP、UDP)
SOCK_STREAM == TCP (默认)
SOCK_DGRAM == UDP
"""
server = socket()
# 2)绑定ip和端口(插电话线)
"""
套接字对象.bind((ip地址,端口))
ip地址 - 找到到服务器对应的计算机;字符串
端口 - 区分计算机中不同的服务(服务指的是正在运行的程序); 整数,范围是0~65535(其中0~1023属于著名端口)
"""
server.bind(('10.7.184.61', 8082))
# 3)开始监听(等待别人打电话)
"""
服务器套接字对象.listen(数量) - 数量决定了同一时间的最大通信数(能处理的客服端最大数量)
"""
server.listen(512)
# 4)让服务器一直运行
while True:
print('等待电话...')
# 1)接受客户端的请求(接电话)
connect, address = server.accept()
print('通话...')
# 2)接受消息
# recv(字节数) - 接受数据(字节数-一次能接受的最大的数据)
re_data = connect.recv(1024)
print(f'接受数据:{address[0]}')
print(str(re_data, encoding='utf-8'))
# 3)发送消息
# with open('index.html', 'r', encoding='utf-8') as f:
# message = f.read()
# connect.send(bytes('HTTP/1.1 200 OK\r\n\r\n '+message, encoding='utf-8'))
connect.send('吃了!'.encode())
4.客户端Client
# 1.创建套接字对象
from socket import socket
client = socket()
# 2.连接服务器(拨号,打电话)
client.connect(('10.7.184.61', 8082))
while True:
# 3.发送消息
# 字符串.encode() - 将转换成二进制数据
message = input('>>>:')
client.send(message.encode(encoding='utf-8'))
# 4.接受消息
# 二进制数据.decode() - 将二进制数00
re_data = client.recv(1024)
print(re_data.decode(encoding='utf-8'))
5.Server持续通信
from socket import socket
server = socket()
server.bind(('10.7.184.61', 8082))
server.listen(512)
\# 让服务器一直运行
while True:
print('等待...')
connect, address = server.accept()
# 建立连接后可以一直通话
while True:
re_data = connect.recv(1024)
print(f'{address[0]}:{re_data.decode()}')
if re_data.decode() == '拜拜':
break
message = input('>>>')
connect.send(message.encode())
if message == '拜拜':
break
print(f’{address[0]}:{re_data.decode()}’)
if re_data.decode() == ‘拜拜’:
break
message = input('>>>')
connect.send(message.encode())
if message == '拜拜':
break