day16總結:運算符重載、拷貝、內存管理和套接字(2019-05-07)

一、運算符重載

  • 通過在類中實現運算符對應的魔法方法,來讓類的對象支持相關運算符的操作
  • python中所有的數據類型都是類,數據都是對象。
  • 所有的運算符對應的操作,本質都是在調用數據類型對應的魔法方法。(每個運算符都對應一個固定的魔法方法)
class Student(object):
    def __init__(self, name, age=0, score=0):
        self.name = name
        self.age = age
        self.score = score

    def __repr__(self):
        return str(self.__dict__)

    # 重載加法預算符
    # self +  other = return 返回值
    def __add__(self, other):
        return self.age + other.age

    # 重載乘法運算符
    def __mul__(self, other):
        return self.score * other

    # >
    def __gt__(self, other):
        return self.score > other.score

    # <
    # def __lt__(self, other):
    #     return self.score < other.score

    # 注意: >和<只需要重載一個


stu1 = Student('小明', 18, 60)
stu2 = Student('小花', 22, 80)

print(stu1 + stu2)
print(stu1 * 10)
print(stu1 > stu2)
print(stu1 < stu2)


all_students = [stu1, stu2, Student('小小', 17, 55), Student('xiaohong', 25, 70)]
all_students.sort()
print(all_students)

補充: 重載

  • 函數的重載:函數名相同但是參數不同的函數可以有多個,叫做函數的重載。(但是python不支持函數的重載)

二、拷貝(面試點)

1.直接賦值

  • 一個變量直接給另外一個變量賦值:直接將地址賦值,賦完后兩個變量指向同一塊內存區域,并且相互影響

2.拷貝原理

  • 將被拷貝的對象復制一份,產生一個新的數據,然后將新的數據的地址返回

3.淺拷貝

  • 列表字典copy方法是淺拷貝、切片也是淺拷貝
  • copy.copy(對象):復制指定的對象,產生一個新的對象(不會復制子對象)
dog1 = Dog('財財')
stu2 = Student('Lisa', 18, 60)
stu2.dog = dog1

stu4 = copy.copy(stu2)

print('stu4:', stu4)
stu2.name = '小花'
print(stu2, stu4)

4.深拷貝

  • copy.deepcopy(對象):復制指定的對象,產生一個新的對象。如果這個對象中有其他的對象,子對象也會被復制
dog1 = Dog('財財')
stu2 = Student('Lisa', 18, 60)
stu2.dog = dog1

stu4 = copy.deepcopy(stu2)

print('stu4:', stu4)
stu2.name = '小花'
print(stu2, stu4)

三、內存管理(面試點)

1. 數據的存儲(內存開辟)

  • python的變量都存儲在棧區間,對象都在堆區間
  • 聲明變量或者給變量賦值,是先在內存(堆)中開辟存儲數據,然后將數據地址保存在變量中
  • 但是數字和字符串特殊,如果是用數字或者字符串給變量賦值,不會直接開辟空間保存數據,而是先在內存檢測這個數據之前是否已經存儲過,如果已經存儲直接用上次保存的數據,沒有存儲才會開辟新的空間保存數據

2. 內存的釋放

1)引用計數
  • python每個對象都有一個屬性叫引用計數,用來保存當前對象的引用的個數
2)垃圾回收機制
  • python中的垃圾回收機制來判斷一個對象是否銷毀,就看這個對象的引用計數是否為零,如果為零就會被銷毀
  • 注意循環引用的問題(另有特殊機制去銷毀)
from sys import getrefcount

list1 = [1, 2]
print(getrefcount(list1))

# def yt_getrefcount(obj):
#     # obj = list1
#     return 獲取obj對應的數據的引用個數

# yt_getrefcount(list1)

# 讓引用計數增加
list2 = list1
print(getrefcount(list1))
dict1 = {'a': list2}
print(getrefcount(list1))

#
# num = 100
# print(getrefcount(num))
# num1 = 100
# print(getrefcount(num))

# 讓引用計數減少
print(getrefcount(list1))
list2 = 100
print(getrefcount(list1))
del dict1['a']
print(getrefcount(list1))
del list1
# print(getrefcount(list1))

四、套接字(socket)

  • 進行通信的兩端就是套接字;有兩種類型,分別是服務器套接字、客戶端套接字
  • 導入socket模塊:from socket import * 或 import socket

1. 服務器套接字(server)

1)創建套接字對象
  • server = socket() 或者 server = socket(family=AF_INET, type=SOCK_STREAM)(默認參數,可省略不寫)
  • 參數說明:
    family:設置ip協議類型, AF_INET(ipv4),AF_INET6(ipv6)
    type:設置傳輸協議類型, SOCK_STREAM(TCP),SOCK_DGRAM(UDP)
2)綁定地址(ip地址和端口)
  • server.bind(('10.7.185.82', 8080))
  • 語法:bind((ip地址, 端口))
  • 參數說明:
    ip地址:字符串,服務器對應的ip地址
    端口號:int, 端口號用來區分一臺電腦上的不同的服務。范圍:0-65535, 其中0-1024是著名端口,一般不選。同一時間一個端口只能綁定一個服務
3)監聽請求
  • server.listen(512)
4)讓服務器一直運行
  • while True:
5)接收請求
  • connect, address = server.accept()
  • 代碼運行到這個位置,會停下來,等到有客戶端給服務器發送請求為止
6)接收數據
  • redata = connect.recv(1024)
  • print(redata.decode(encoding='utf-8'))
  • 參數說明:
    recv(bufsize):bufsize,設置一次性能夠接收的數據大小的最大值,單位是字節
    返回的數據類型是字節
7)發送數據
  • send_message = input('輸入文字:')
  • connect.send(send_message.encode())
8)關閉連接
  • connect.close()
實例:
from socket import *

# 1.創建套接字對象
server = socket()
# 2.綁定地址
server.bind(('10.7.185.82', 8080))
# 3.監聽
server.listen(512)

# 4.讓服務器一直運算
while True:
    print('開始監聽....')
    # 5. 接受請求
    connect, address = server.accept()

    # 6.接收數據
    redata = connect.recv(1024)
    message = redata.decode(encoding='utf-8')

    # 7.發送數據
    if message == 'text':
        # 發送文字
        send_message = input('輸入文字:')
        connect.send(send_message.encode())
    elif message == 'image':
        # 發送圖片
        with open('server/luffy4.jpg', 'rb') as f:
            image_data = f.read()
        # connect.send('你好'.encode())
        connect.send(('{"type":"jpg", "lengh":%d}' % len(image_data)).encode())
        connect.send(image_data)

    # 8.關閉連接
    connect.close()

2. 客戶端套接字(client)

1)創建套接字對象
  • client = socket()
2)連接服務器
  • client.connect(('10.7.185.82', 8085))
3)發送數據
  • message = input('請輸入:')
  • client.send(message.encode())
4)接收數據
  • re_data = client.recv(1024)
  • print(re_data.decode(encoding='utf-8'))
實例:
from socket import socket

# 1.創建套接字對象
client = socket()

# 2.連接服務器
client.connect(('10.7.185.82', 8080))

# 3.發送數據
print('1.獲取文字請輸入text\n2.獲取圖片請輸入image')
send_message = input(':')
client.send(send_message.encode())

# 4.接收數據
if send_message == 'text':
    text_data = client.recv(1024)
    print(text_data.decode(encoding='utf-8'))
elif send_message == 'image':
    image_message = client.recv(1024)
    print(image_message.decode(encoding='utf-8'))

    while True:
        image_data = client.recv(1024)
        if len(image_data) == 0:
            break

        with open('client/image.jpg', 'ab') as f:
            f.write(image_data)

client.close()
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容