python中所有的數(shù)據(jù)類型都是诽凌,數(shù)據(jù)都是對(duì)象。
所有的運(yùn)算符對(duì)應(yīng)的操作坦敌,本質(zhì)都是在調(diào)用數(shù)據(jù)類型對(duì)應(yīng)的魔法方法侣诵。(每個(gè)運(yùn)算符都對(duì)應(yīng)一個(gè)固定的魔法方法)
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__)
# 重載加法預(yù)算符
# self + other = return 返回值
def __add__(self, other):
return self.age + other.age
# 重載乘法運(yùn)算符
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
# 注意: >和<只需要重載一個(gè)
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)
練習(xí): 讓Student的對(duì)象支持乘法運(yùn)算,運(yùn)算規(guī)則是:
<name: 張三, age:10, score:0> * 3 = [<name: 張三, age:10, score:0> , <name: 張三, age:10, score:0> , <name: 張三, age:10, score:0> ]
import copy
class Dog:
def __init__(self, name, color='黃色'):
self.name = name
self.color = color
class Student:
def __init__(self, name, age=0, score=0):
self.name = name
self.age = age
self.score = score
self.dog = None
def __repr__(self):
return '<'+str(self.__dict__)[1:-1]+'>'
# *
def __mul__(self, other):
# self = stu1, other = 2
result = []
for _ in range(other):
result.append(self)
return result
stu1 = Student('張三', 18, 90)
print(stu1)
result = stu1 * 2
print(result)
stu1.name = '小明'
print(result)
result[0].name = '小花'
print(stu1, result)
print('=====================深拷貝和淺拷貝====================')
print('======直接賦值=====')
1.一個(gè)變量直接給另外一個(gè)變量賦值:直接將地址賦值狱窘,賦完后兩個(gè)變量指向同一塊內(nèi)存區(qū)域杜顺,并且相互影響
stu2 = Student('Lisa', 18, 60)
stu3 = stu2
print(id(stu3), id(stu2))
stu2.age = 28
print(stu3)
2.淺拷貝和深拷貝(面試點(diǎn)!)
拷貝原理: 將被拷貝的對(duì)象復(fù)制一份蘸炸,產(chǎn)生一個(gè)新的數(shù)據(jù)躬络,然后將新的數(shù)據(jù)的地址返回
a.淺拷貝
- 列表或字典的copy方法是淺拷貝、切片也是淺拷貝
- copy.copy(對(duì)象) - 復(fù)制指定的對(duì)象搭儒,產(chǎn)生一個(gè)新的對(duì)象(不會(huì)復(fù)制子對(duì)象)
b.深拷貝
copy.deepcopy(對(duì)象) - 復(fù)制指定的對(duì)象穷当,產(chǎn)生一個(gè)新的對(duì)象。如果這個(gè)對(duì)象中有其他的對(duì)象仗嗦,子對(duì)象也會(huì)被復(fù)制
"""
print('======淺拷貝=====')
dog1 = Dog('財(cái)財(cái)')
stu2 = Student('Lisa', 18, 60)
stu2.dog = dog1
stu4 = copy.copy(stu2)
print('stu4:', stu4)
stu2.name = '小花'
print(stu2, stu4)
print('======深拷貝=====')
dog1 = Dog('財(cái)財(cái)')
stu2 = Student('Lisa', 18, 60)
stu2.dog = dog1
stu4 = copy.deepcopy(stu2)
print('stu4:', stu4)
stu2.name = '小花'
from sys import getrefcount
1.數(shù)據(jù)的存儲(chǔ)(內(nèi)存開辟)
python的變量都存儲(chǔ)在棧區(qū)間膘滨,對(duì)象都在堆區(qū)間。
聲明變量或者給變量賦值稀拐,是先在內(nèi)存(堆)中開辟存儲(chǔ)數(shù)據(jù)火邓,然后將數(shù)據(jù)地址保存在變量中。
但是數(shù)字和字符串特殊德撬,如果是用數(shù)字或者字符串給變量賦值铲咨,不會(huì)直接開辟空間保存數(shù)據(jù),
而是先在內(nèi)存檢測(cè)這個(gè)數(shù)據(jù)之前是否已經(jīng)存儲(chǔ)過(guò)蜓洪,如果已經(jīng)存儲(chǔ)直接用上次保存的數(shù)據(jù)纤勒,沒(méi)有存儲(chǔ)才會(huì)開辟新的空間保存數(shù)據(jù)
2. 內(nèi)存的釋放
1)引用計(jì)數(shù)
python每個(gè)對(duì)象都有一個(gè)屬性叫引用計(jì)數(shù),用來(lái)保存當(dāng)前對(duì)象的引用的個(gè)數(shù)隆檀。
python中的垃圾回收機(jī)制來(lái)判斷一個(gè)對(duì)象是否銷毀摇天,就看這個(gè)對(duì)象的引用計(jì)數(shù)是否為零,如果為零就會(huì)被銷毀恐仑。
list1 = [1, 2]
list2 = [1, 2]
print(id(list1), id(list2))
num1 = 10
num2 = 10
print(id(num1), id(num2))
class Student:
def __init__(self):
self.name = '張三'
print('==============引用計(jì)數(shù)===========')
list1 = [1, 2]
print(getrefcount(list1))
# def yt_getrefcount(obj):
# # obj = list1
# return 獲取obj對(duì)應(yīng)的數(shù)據(jù)的引用個(gè)數(shù)
# yt_getrefcount(list1)
# 讓引用計(jì)數(shù)增加
list2 = list1
print(getrefcount(list1))
dict1 = {'a': list2}
print(getrefcount(list1))
#
# num = 100
# print(getrefcount(num))
# num1 = 100
# print(getrefcount(num))
# 讓引用計(jì)數(shù)減少
print(getrefcount(list1))
list2 = 100
print(getrefcount(list1))
del dict1['a']
print(getrefcount(list1))
del list1
# print(getrefcount(list1))