1.多繼承
- python中的類支持多繼承(讓一個(gè)類同時(shí)繼承多個(gè)類)
- 多繼承的時(shí)候,子類只能繼承第一個(gè)父類中所有的屬性和方法,后面的父類中只有字段和方法可以被繼承
- 實(shí)際上:子類能繼承第一個(gè)父類的所有屬性和方法,后面的父類,只能繼承前面沒(méi)有的字段和方法(不重名的)
class Animal(object):
num = 100
name = 'hh'
def __init__(self):
self.age = 0
self.gender = 'male'
@classmethod
def func1(cls):
print('動(dòng)物類的類方法')
class Fly(object):
name = '飛行器'
def __init__(self):
self.height = 100
self.time = 20
self.spend = 100
def func1(self):
print('紅紅火火')
def func2(self):
print('飛行的對(duì)象方法')
class Bird(Animal,Fly):
pass
bird = Bird()
print(Bird.num,Bird.name)
bird.func1()
bird.func2()
print(bird.age)
運(yùn)算符重載
import copy
python中所有的類型都是類,所以所有的數(shù)據(jù)都是對(duì)象
python中使用任意的運(yùn)算符都是在調(diào)用相應(yīng)類中的相應(yīng)方法,每一個(gè)運(yùn)算符對(duì)應(yīng)什么方法是固定
某種數(shù)據(jù)是否支持某個(gè)運(yùn)算符操作就看這個(gè)數(shù)據(jù)類型中是否實(shí)現(xiàn)了對(duì)應(yīng)的方法
2.運(yùn)算符重載指的是在不同的類中實(shí)現(xiàn)同樣的運(yùn)算符對(duì)應(yīng)的函數(shù)
類的對(duì)象默認(rèn)情況下只支持:==,!=
class Student:
def __init__(self, name, age, score=0):
self.name = name
self.age = age
self.score = score
def __repr__(self):
return str(self.__dict__)
# a+b -> a.__add__(b)
# self -> 當(dāng)前類的對(duì)象,也就是+前面的那個(gè)數(shù)據(jù)
# other -> +后面的那個(gè)數(shù)據(jù),類型根據(jù)運(yùn)算規(guī)則的設(shè)計(jì)可以是任何類型的數(shù)據(jù)
def __add__(self, other):
# return self.age + other.age
# return self.score + other.score
return self.name + other.name, self.age + other.age, self.score + other.score
# return 'abc'
def __mul__(self, other):
list1=[]
for _ in range(other):
list1.append(copy.copy(other))
return list1
# 大于和小于運(yùn)算符只需要重載一個(gè),另外一個(gè)自動(dòng)實(shí)現(xiàn)
def __lt__(self, other):
return self.score < other.score
stu1 = Student('小明', 12, 34)
stu2 = Student('小胡', 15, 67)
stu3 = Student('小胡', 15, 47)
print(stu1 == stu2, stu1 != stu2) # False True
print(stu1 + stu2) # return self.age + other.age 27
print(stu1 + stu2) # return self.score + other.score 101
print(stu1 + stu2) # return self.name + other.name,self.age + other.age,self.score + other.score ('小明小胡', 27, 101)
print(stu1 + stu2) # return 'abc' abc
students = [stu1, stu2, stu3]
students.sort()
print(students)
""" = = = HJR = = = """
from copy import copy, deepcopy
# 支持所有類型的拷貝
class Dog:
def __init__(self,name,color):
self.name=name
self.color=color
def __repr__(self):
return '<%s,id:%s>' % (str(self.__dict__)[1:-1],hex(id(self)))
class Person:
def __init__(self,name,age,dog):
self.name = name
self.age = age
self.dog = dog
def __repr__(self):
return '<%s,id:%s>' % (str(self.__dict__)[1:-1],hex(id(self)))
p1 = Person('小米',18,Dog('大黃','黃色'))
1.直接賦值
將變量中的地址直接賦給新的變量,賦值后兩個(gè)變量的地址相同
p2 = p1
print(id(p1),id(p2)) # 3032819635872 3032819635872
p1.name = '小花'
print(p1.name,p2.name) # 小花 小花
2.拷貝
不管是淺拷貝還是深拷貝都會(huì)對(duì)原數(shù)據(jù)進(jìn)行賦值產(chǎn)生新的地址
淺拷貝只拷貝當(dāng)前對(duì)象,不會(huì)拷貝子對(duì)象,還是與原來(lái)的子對(duì)象相關(guān)聯(lián)
深拷貝拷貝所有,完全與原對(duì)象分離
print(id(p1),id(copy(p1)),id(deepcopy(p1))) # 2045139556000 2045139556168 2045139556728
3.淺拷貝
字符串、列表和元祖的切片;對(duì)象.copy();copy模塊中的copy方法都是淺拷貝
p3 = copy(p1)
print(p1,p3) # <'name': '小花', 'age': 18, 'dog': <'name': '大黃', 'color': '黃色',id:0x29a6c9213c8>,id:0x29a6c921668> <'name': '小花', 'age': 18, 'dog': <'name': '大黃', 'color': '黃色',id:0x29a6c9213c8>,id:0x29a6c921668>
p3.dog.name = '哈尼'
p3.name = '小童'
print(p1,p3) # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黃色',id:0x285c82e13c8>,id:0x285c82e1668> <'name': '小童', 'age': 18, 'dog': <'name': '哈尼', 'color': '黃色',id:0x285c82e13c8>,id:0x285c82e1940>
# 發(fā)現(xiàn)dog中的改變會(huì)一同改變
# 4.深拷貝
"""
copy模塊中的deepcopy為深拷貝,有且僅有這一個(gè)
"""
p4 = deepcopy(p1)
print(p1,p4) # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黃色',id:0x15086f915f8>,id:0x15086f916a0> <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黃色',id:0x15086f915f8>,id:0x15086faae10>
p4.dog.name = '大華'
p4.name = '小美'
print(p1,p4) # <'name': '小花', 'age': 18, 'dog': <'name': '哈尼', 'color': '黃色',id:0x1d71fee15f8>,id:0x1d71fee16a0> <'name': '小美', 'age': 18, 'dog': <'name': '大華', 'color': '黃色',id:0x1d71fefaeb8>,id:0x1d71fefada0>
練習(xí)
a = ['color','height','background']
b = [a,'aaa','bbb']
c1 = b
c2 = copy(b)
c3 = deepcopy(b)
a[-1] = ['BG']
b.append('ccc')
# [['color','height',['BG']],'aaa','bbb','ccc']
# [['color','height',['BG']],'aaa','bbb']
# [['color', 'height', 'background'], 'aaa', 'bbb']
# 問(wèn)題:print(c1),print(c2),print(c3)的打印結(jié)果
""" = = = HJR = = = """
from enum import Enum,unique
枚舉值的特點(diǎn):
1.可以通過(guò)有意義的屬性名直接顯示數(shù)據(jù)
2.每個(gè)數(shù)據(jù)的值不能修改
3.可以做到不同的數(shù)據(jù)是唯一的
unique確保不同的數(shù)據(jù)是唯一的
在類中繼承Enum可以做到枚舉
@unique
class PokerNum(Enum):
J = 11
Q = 12
K = 13
print(PokerNum.J) # PokerNum.J
print(PokerNum.J.value > PokerNum.Q.value) # False
""" = = = HJR = = = """
獲取引用計(jì)數(shù)
from sys import getrefcount
1.內(nèi)存的開(kāi)辟
內(nèi)存區(qū)間分為棧區(qū)間和堆區(qū)間;棧區(qū)間的內(nèi)存自動(dòng)開(kāi)辟自動(dòng)釋放,堆區(qū)間的內(nèi)存需要程序員手動(dòng)開(kāi)辟手動(dòng)釋放;
但是python已經(jīng)將堆區(qū)間內(nèi)存的開(kāi)辟和釋放自動(dòng)化
a. 當(dāng)給變量賦值的時(shí)候,系統(tǒng)會(huì)先在堆區(qū)間中開(kāi)辟空間將數(shù)據(jù)存起來(lái),然后再將數(shù)據(jù)在隊(duì)中的地址存到變量中,變量存在棧區(qū)間;
b. 數(shù)字和字符串?dāng)?shù)據(jù)在開(kāi)辟空間的時(shí)候,會(huì)先檢查內(nèi)存中之前是否已經(jīng)有這個(gè)數(shù)據(jù),
如果有,直接使用之前的數(shù)據(jù),不再開(kāi)辟空間,如果沒(méi)有,才重新開(kāi)辟空間
a, b = [1, 2, 3], [1, 2, 3]
print(id(a), id(b), a is b) # 1567575270024 1567575270088 False
print(id(a[0]),id(b[0]), a[0] is b[0]) # 140726342640464 140726342640464 True
a, b = 10, 10
print(id(a), id(b), a is b) # 140726342640752 140726342640752 True
a, b = '10', '10'
print(id(a), id(b), a is b) # 1567575737208 1567575737208 True
2,內(nèi)存的釋放
棧區(qū)間:全局棧區(qū)間在程序結(jié)束后銷毀,函數(shù)棧區(qū)間在函數(shù)調(diào)用結(jié)束后銷毀(自動(dòng))
堆區(qū)間:看一個(gè)對(duì)象是否銷毀,就看這個(gè)對(duì)象的引用計(jì)數(shù)是否為0;
如果一個(gè)對(duì)象的引用計(jì)數(shù)為0,這個(gè)對(duì)象就銷毀,反之不銷毀(垃圾回收機(jī)制)
注意:python中針對(duì)對(duì)象的循環(huán)引用,已經(jīng)做了處理,程序員不需要寫(xiě)額外的代碼來(lái)解決循環(huán)引用的問(wèn)題
a = [1, 2, 3]
print(getrefcount(a)) # 2 會(huì)打印比之前多一個(gè)引用,因?yàn)楹瘮?shù)本身會(huì)有一個(gè)
def fun(a={}):
a[1]=3
return a
print(fun())
print(fun())