多繼承
1.多繼承
python中的類(lèi)支持多繼承
class 子類(lèi)(父類(lèi)1, 父類(lèi)2,...):
pass
class Fly(object):
"""飛行類(lèi)"""
f_num = 10
def __init__(self):
self.height = 0
self.speed = 0
self.time = 0
def start(self, speed):
self.speed = speed
# print(self.speed)
? print('開(kāi)始飛行')
class Animal(object):
num = 100
def __init__(self):
self.age = 0
self.gender = '公'
@staticmethod
def eat(food: str):
print('吃'+food)
class Bird(Animal, Fly):
pass
b1 = Bird()
# 字段都可以繼承
print(Bird.f_num, Bird.num) # 10, 100
# 方法都可以繼承
b1.start(10)
Bird.eat('肉')
# 只能繼承第一個(gè)父類(lèi)的對(duì)象屬性
# print(b1.age, b1.gender)
# print(b1.height, b1.time, b1.speed)
運(yùn)算符的重載
1. 運(yùn)算符
python中所有的數(shù)據(jù)類(lèi)型本質(zhì)都是類(lèi)皂岔, 所有的數(shù)據(jù)本質(zhì)就是對(duì)象旭从。
在使用運(yùn)算符對(duì)數(shù)據(jù)進(jìn)行操作的時(shí)候,實(shí)質(zhì)是調(diào)用運(yùn)算符對(duì)應(yīng)的魔法方法;
運(yùn)算符前面的數(shù)據(jù)類(lèi)型琼掠,決定了函數(shù)哪個(gè)類(lèi)中對(duì)應(yīng)的魔法方法
每個(gè)運(yùn)算符都有自己固定的魔法方法, 看某種類(lèi)型的數(shù)據(jù)是否支持某種運(yùn)算符就看這個(gè)類(lèi)型中有沒(méi)有實(shí)現(xiàn)對(duì)應(yīng)的魔法方法
例如: + - add
> - gt
class Student:
def __init__(self, name, age, score=0):
self.name = name
self.age = age
self.score = score
def __repr__(self):
return '<%s>' % str(self.__dict__)[1:-1]
# +號(hào)對(duì)應(yīng)的魔法方法:實(shí)現(xiàn)兩個(gè)對(duì)象求和
# self + other -> self.__add__(other)
# 函數(shù)的返回值就是運(yùn)算結(jié)果
def __add__(self, other):
print('self:', self.name)
print('other:', other.name)
return self.age + other.age
# *號(hào)對(duì)應(yīng)的魔法方法:實(shí)現(xiàn)對(duì)象乘以整數(shù)
def __mul__(self, other):
return self.age * other
# 注意: >和<只需要重載一個(gè)贱鼻,另外一個(gè)自動(dòng)支持
# self < other
def __lt__(self, other):
return self.score < other.score
stu1 = Student('小明', 19, 90)
stu2 = Student('小胡', 20, 89)
print(stu1 == stu2) # False
print(stu1 + stu2) # stu1.__add__(stu2)
# print(stu1 > stu2)
print('abc'*4)
print(stu1 * 2) # stu1.__mul__(2)
all_student = [
Student('stu1', 17, 90),
Student('stu2', 20, 89),
Student('stu3', 12, 70),
Student('stu4', 40, 81)
]
print(all_student)
# 問(wèn)題
# all_student.sort() # TypeError: '<' not supported between instances of 'Student' and 'Student'
# 解決方案一:給key賦值
# all_student.sort(key=lambda item: item.score)
# print(all_student)
# 解決方案二: 重載<運(yùn)算符
# all_student.sort()
# print(all_student)
print(stu1 < stu2)
print(stu1 > stu2)
print(max(all_student))
內(nèi)存管理
手動(dòng)內(nèi)存管理
內(nèi)存分為棧區(qū)間和堆區(qū)間僵朗,棧區(qū)間中的內(nèi)存是自動(dòng)開(kāi)辟自動(dòng)釋放; 堆上的內(nèi)存需要程序員寫(xiě)代碼申請(qǐng)和釋放
1.內(nèi)存的開(kāi)辟
python中所有的類(lèi)型就是類(lèi),所以所有的數(shù)據(jù)都是對(duì)象捏悬。對(duì)象都是保存在堆區(qū)間撞蚕;變量是保存在棧區(qū)間,
變量中實(shí)際存儲(chǔ)的是堆中存儲(chǔ)的數(shù)據(jù)的地址过牙。(變量的本質(zhì)就是指針)
注意: 除了數(shù)字和字符串對(duì)象甥厦,其他的數(shù)據(jù)都是每次需要數(shù)據(jù)的時(shí)候直接在堆中開(kāi)辟空間。
數(shù)字和字符串會(huì)先檢查這個(gè)數(shù)據(jù)之前是否保存過(guò)寇钉,如果保存過(guò)就直接用之前的數(shù)據(jù),否則才開(kāi)辟新的內(nèi)存空間
from sys import getrefcount
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(id(list1), id(list2))
list3 = list2
num1 = '100'
num2 = '100'
print(id(num1), id(num2))
num1 = 2**1999
num2 = 2**1999
print(id(num1), id(num2))
# def change(x, y):
# temp = x
# x = y
# y = temp
#
#
# a = 10
# b = 20
# change(a, b)
# print(a, b)
2.內(nèi)存的釋放
python中內(nèi)存的釋放采用的是'垃圾回收機(jī)制'自動(dòng)釋放
a.垃圾回收機(jī)制: 1)看一個(gè)數(shù)據(jù)是否需要銷(xiāo)毀(是否需要回收)刀疙,就看這個(gè)對(duì)象的引用計(jì)數(shù)是否為0(引用:保存對(duì)象地址的數(shù)據(jù))。
2)如果這個(gè)對(duì)象的引用計(jì)數(shù)不為零就假設(shè)當(dāng)前對(duì)象消失摧莽,然后看會(huì)不會(huì)有其他對(duì)象因?yàn)樗南б糜?jì)數(shù)變成0庙洼,
如果有,就將另外一個(gè)對(duì)象回收(循環(huán)引用解環(huán))
注意: 用一個(gè)變量給另外一個(gè)變量賦值镊辕,實(shí)質(zhì)賦的是地址
list1 = [10, 20, 30]
print(getrefcount(list1))
list2 = list1
print(getrefcount(list1))
# def yt_getrefcount(obj):
# # obj = list1
# print('獲取obj的引用次數(shù)')
#
# print(yt_getrefcount(list1))
num = 100
print(getrefcount(num))
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
self.dog = None
class Dog:
def __init__(self, name, age, color):
self.name = name
self.age = age
self.color = color
self.owner = None
p1 = Person('小明', 18)
dog1 = Dog('財(cái)財(cái)', 3, '黃色')
p1.dog = dog1
dog1.owner = p1
del p1
del dog1
# 面試題:== 和 is的區(qū)別?
# 補(bǔ)充: is的使用 - 判斷兩個(gè)數(shù)據(jù)的地址是否一樣
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(list1 == list2, list1 == list3) # True, True
print(list1 is list2, list1 is list3) # False, True
深拷貝和淺拷貝
import copy
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
self.dog = None
def __repr__(self):
return '<%s>' % str(self.__dict__)[1:-1]
class Dog:
def __init__(self, name, color):
self.name = name
self.color = color
def __repr__(self):
return '<%s>' % str(self.__dict__)[1:-1]
使用變量的三種情況:
1.直接賦值 - 賦的是地址油够,賦完值兩個(gè)變量一模一樣
變量1 = 變量2
list1 = [1, 2, 3]
list2 = list1
list1.append(10)
print(list1) # [1, 2, 3, 10]
print(list2) # [1, 2, 3, 10]
2.淺拷貝
列表[:]、列表.copy()征懈、copy.copy(數(shù)據(jù))
淺拷貝: 直接復(fù)制被拷貝的數(shù)據(jù)產(chǎn)生一個(gè)新的地址石咬,將新的地址賦給變量; 如果被拷貝的對(duì)象中有子對(duì)象,子對(duì)象不會(huì)被復(fù)制
p1 = Person('小明', 18, '男')
p1.dog = Dog('大黃', '黃色')
# p2 = p1
print('============淺拷貝==============')
p2 = copy.copy(p1)
p2.name = 'Tom'
p2.dog.color = '褐色'
print(p1) # <'name': '小明', 'age': 18, 'gender': '男'>
print(p2) # <'name': 'Tom', 'age': 18, 'gender': '男'>
3.深拷貝
copy.deepcopy(數(shù)據(jù))
深拷貝: 直接復(fù)制被拷貝的數(shù)據(jù)產(chǎn)生一個(gè)新的地址卖哎,將新的地址賦給變量; 如果被拷貝的對(duì)象中有子對(duì)象鬼悠,子對(duì)象也會(huì)被復(fù)制
print('============深拷貝==============')
p1 = Person('小明', 18, '男')
p1.dog = Dog('大黃', '黃色')
p3 = copy.deepcopy(p1)
p3.name = '小花'
p3.gender = '女'
p3.dog.color = '紅色'
print(p1)
print(p3)
a = 10
b = 257
c1 = 257
def te():
c = 10
d = 257
print(a is c)
print(b is d)
print(id(a),id(b),id(c),id(d))
te()
print(id(c1), id(b))