一蓖乘、復(fù)習(xí)
1.類(lèi)的聲明
class 類(lèi)名:
類(lèi)的雷類(lèi)容
2.類(lèi)的屬性
屬性就是聲明在類(lèi)中的變量
a.對(duì)象屬性:值會(huì)因?yàn)閷?duì)象的不同而不同
聲明在 init 方法中,
self.屬性 = 值
對(duì)象.屬性
b.類(lèi)的字段:值不會(huì)因?yàn)閷?duì)象的不同而不同
直接聲明在類(lèi)中
變量名 = 值
對(duì)象.屬性
3.方法
a.對(duì)象方法:直接聲明在類(lèi)中,自帶 self 參數(shù),調(diào)用的時(shí)候不用傳參,誰(shuí)調(diào)用就指向誰(shuí)
對(duì)象.方法()
實(shí)現(xiàn)函數(shù)的功能需要對(duì)象屬性時(shí)
(1) init 方法:系統(tǒng)創(chuàng)建對(duì)象的時(shí)候,系統(tǒng)會(huì)自動(dòng)調(diào)用, 需要通過(guò)構(gòu)造方法來(lái)給
b.類(lèi)方法:聲明前加 @classmethod,自帶 cls 參數(shù),調(diào)用的時(shí)候,不用傳參,誰(shuí)調(diào)用就指向誰(shuí)
類(lèi).方法()
實(shí)現(xiàn)函數(shù)的功能需要類(lèi)的字段時(shí)
c.靜態(tài)方法:聲明前加 @stadicmethod 沒(méi)有自帶參數(shù)
類(lèi).方法()
實(shí)現(xiàn)函數(shù)的功能既不需要需要對(duì)象屬性,也不需要類(lèi)的字段時(shí)
二、私有化:
1.屬性和方法
保護(hù)的:在外部不可以使用,可以繼承
公開(kāi)的:在外部可以使用觉啊,可以繼承
2.python 的的私有化
在 python 中,屬性或者方法名前加 (--),就可以加將屬性或者方法變成私有的(注意)
私有的屬性和方法只能在類(lèi)的內(nèi)部使用递雀,不能在類(lèi)的外面使用柄延。
3.python 私有化的原理
在名字前是 __ 的屬性和方法前再加 '_類(lèi)名' 去保存屬性和方法
class Person:
num = 61
__num2 = 62
def __init__(self, name='張三', age=0):
self.name = name
self.age = age
self.__sex = '男'
def eat(self, food):
print(self.__sex)
print(self.name, food)
self.__run()
def __run(self):
print('%s在跑步' % self.name)
@classmethod
def show_num(cls):
print('人類(lèi)的數(shù)量:%d, %d' % (cls.num, cls.__num2))
@staticmethod
def func1():
print('人類(lèi)要保護(hù)大自然!')
def main():
p1 = Person()
print(Person.num)
# print(Person.__num2)
print(p1.name)
# print(p1.__sex)
print(p1._Person__sex)
p1.eat('面條')
# p1.run()
Person.show_num()
Person.func1()
print(p1.__dict__)
if __name__ == '__main__':
main()
三、getter & setter
1.應(yīng)用 getter 的場(chǎng)景:
getter : 獲取屬性的值之前想要做一些別的事情,就給這個(gè)屬性添加 getter
setter : 給對(duì)象屬性賦值之前想要做一些別的事情,就給這個(gè)屬性添加 setter
2.getter :
第一步:申明屬性時(shí),在屬性前加 ''
第二步:聲明函數(shù) @property (函數(shù)沒(méi)有除了 self 以外的參數(shù),但是要有返回值.返回值就是獲取)
def 去掉 '' 的屬性名(self):
做點(diǎn)別的事情
返回屬性的值
第三步:
在類(lèi)的外部,通過(guò)對(duì)象.去掉_的屬性去獲取相關(guān)
3.setter :
想要添加 setter 必須要先添加 getter
第一步: 聲明屬性的時(shí)候在屬性名前面加 _
第二步:聲明函數(shù)(函數(shù)除了 self 以外還需要一個(gè)參數(shù),沒(méi)有返回值.之類(lèi)的參數(shù)代表給屬性賦的值)
@屬性名去掉.setter
def 去掉的屬性名(self, 參數(shù)):
做點(diǎn)別的事情
給屬性賦值
第三步:在類(lèi)的外部通過(guò) 對(duì)象.去掉_ 的屬性去給相關(guān)屬性賦值
例如:
class Person:
def __init__(self, name=''):
self.name = name
self._age = 0
self._week = 1 # 屬性名前面有 _ ,使用屬性的時(shí)候不要直接使用
# 添加 setter
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if not isinstance(value, int):
raise ValueError
if not (0 <= value <= 150):
raise ValueError
self._age = value
# 給 week 添加 getter
@property
def week(self):
print('---------------------------------')
if self._week < 7:
return '星期 %d ' % self._week
else:
print('星期天')
@week.setter
def week(self, value):
self._week = value
def main():
p1 = Person('阿黃')
p1.age = 23
p1.age = 2
print(p1.week)
p1.week = 5
if __name__ == '__main__':
main()
運(yùn)行效果:
---------------------------------
星期 1
四 、繼承
1.什么是繼承
一個(gè)類(lèi)繼承一個(gè)類(lèi),其中會(huì)產(chǎn)生繼承者和被繼承者,這里的繼承者加子類(lèi),被繼承者叫父類(lèi)/超類(lèi);
繼承就是讓子類(lèi)直接擁有父類(lèi)的方法和屬性;
2.怎么繼承
class 類(lèi)名(父類(lèi)列表)
類(lèi)的內(nèi)容
說(shuō)明:
a.python 中所有的類(lèi)都是直接或間接繼承自基類(lèi) object
class 類(lèi)名 --> class類(lèi)名(object)
b.python 中的繼承支持多繼承,父類(lèi)列表中可以擁有多個(gè)類(lèi),多各類(lèi)之間用逗號(hào)隔開(kāi)
3.繼承能繼承那些東西
所有的屬性和方法都能繼承,私有的屬性都可以繼承
注意:slots的值不會(huì)被繼承,如果在類(lèi)中給 slots 賦值后,當(dāng)前類(lèi)的對(duì)象不能使用 dict;但是這個(gè)類(lèi)的子類(lèi)對(duì)象可以使用__dict
只是 dict 中沒(méi)有從父類(lèi)繼承下來(lái)的屬性
如果父類(lèi)沒(méi)有給slots賦值,直接給子類(lèi)的slots,會(huì)無(wú)效
例如:
class Person(object):
num1 = 123
def __init__(self, name='', age=0, sex='男'):
self.name = name
self.age = age
self.sex = sex
def eat(self, food):
print(' %s 在吃 %s' % (self.name, food))
@classmethod
def show_num(cls):
print('人類(lèi)的數(shù)量為 : %s' % cls.num1)
class Student(Person):
pass
def main():
Student.num1 = 5000000
print(Student.num1)
stu = Student('阿黃')
stu.eat('火鍋')
Student.show_num()
if __name__ == '__main__':
main()
運(yùn)行效果:
5000000
阿黃 在吃 火鍋
人類(lèi)的數(shù)量為 : 5000000
五搜吧、添加屬性和方法
1.添加方法
直接在子類(lèi)中聲明新的方法
子類(lèi)可以使用父類(lèi)的屬性和方法,但是父類(lèi)不能使用子類(lèi)添加的屬性和方法
2.方法的重寫(xiě)
在子類(lèi)中重新實(shí)現(xiàn)父類(lèi)已經(jīng)擁有的方法 -----完全重寫(xiě)
在重寫(xiě)這個(gè)函數(shù)時(shí),需要保留父類(lèi)的功能在子類(lèi)中添加新的功能
-----部分重寫(xiě)(在子類(lèi)中通過(guò)'super().'的方式調(diào)用父類(lèi)方法后添加新的代碼)
3.類(lèi)中函數(shù)的調(diào)用過(guò)程
a.
回到函數(shù)聲明的位置,先看當(dāng)前類(lèi)中是否有方法,如果有就直接調(diào)用當(dāng)前類(lèi)中的方法;,沒(méi)有就去看父類(lèi)中有沒(méi)有這個(gè)方法,
如果父類(lèi)中也沒(méi)有,就看父類(lèi)的父類(lèi),以此類(lèi)推,,,直到找到 object 類(lèi),如果 object 類(lèi)里面也是沒(méi)有,程序就報(bào)錯(cuò)
b.添加類(lèi)的字段
c.添加對(duì)象屬性
對(duì)象屬性其實(shí)是由 init 方法繼承下來(lái)的
例如:
class Person(object):
num1 = 123
def __init__(self, name, sex='男'):
self.name = name
self.age = 3
self.sex = sex
def eat(self, food):
print(' %s 再吃 %s' % (self.name, food))
@classmethod
def show_num(cls):
print('人類(lèi)的數(shù)量為 : %s' % cls.num1)
class StudentPlus(Person):
def __init__(self, sno, name=None):
self.name = name
self.sno = sno
self.sex = '男'
self.age = 3
self.score = 90
class Student(Person):
def student(self):
print('%s 在睡覺(jué)' % self.name)
@classmethod
def show_num(cls):
print('學(xué)生的數(shù)量為: %d ' % cls.num1)
def main():
p1 = Person('阿黃')
stu1 = Student('大白')
stu1.student()
Person.show_num()
Student.show_num()
if __name__ == '__main__':
main()
運(yùn)行效果:
大白 在睡覺(jué)
人類(lèi)的數(shù)量為 : 123
學(xué)生的數(shù)量為: 123
六市俊、多繼承
一個(gè)類(lèi)同時(shí)繼承多個(gè)類(lèi)
多繼承:
class 類(lèi)名(父類(lèi)1, 父類(lèi)2, 父類(lèi)3......)
類(lèi)的內(nèi)容
多個(gè)父類(lèi)中的所有方法和字段都可以繼承,只是對(duì)象屬性只能繼承第一個(gè)父類(lèi)的
例如:
class Animal:
def __init__(self, name, age=0, color='黑色'):
self.name = name
self.age = age
self.color = color
def func1(self):
print('對(duì)象 方法')
class Fly:
def __init__(self):
self.height = 100000
class Bride(Animal, Fly):
pass
def main():
p1 = Bride('阿黃')
print(p1.__dict__)
# print(p1.height) # 報(bào)錯(cuò)。 AttributeError: 'Bride' object has no attribute 'height'
if __name__ == '__main__':
main()
運(yùn)行效果:
{'name': '阿黃', 'age': 0, 'color': '黑色'}
七滤奈、運(yùn)算符的重載
1.什么是運(yùn)算符重載
通過(guò)實(shí)現(xiàn)類(lèi)中相應(yīng)的魔法方法,來(lái)讓自己的對(duì)象支持相應(yīng)的運(yùn)算符
注意:python 中所有的數(shù)據(jù)類(lèi)型都是類(lèi),所有的數(shù)據(jù)都是對(duì)象
例如:
class Student:
def __init__(self, name='', age=0, score=0):
self.name = name
self.age = age
self.score = score
# 返回值就是運(yùn)算結(jié)果
def __add__(self, other):
# 支持學(xué)生加學(xué)生
return self.age + other.age
# 大于和小于符號(hào)只需要重載一個(gè)后可以了
def __gt__(self, other):
return self.score > other.score
def main():
stu1 = Student('阿黃', 3, 50)
stu2 = Student('阿黃', 5, 50)
print(stu1 + stu2) # 相當(dāng)于: print(stu1.__add__(stu2))
if __name__ == '__main__':
main()
運(yùn)行效果:
8
八摆昧、內(nèi)存管理機(jī)制
1.數(shù)據(jù)的存儲(chǔ)(分為棧區(qū)間和堆區(qū)間)
棧區(qū)間:從底層來(lái)看,系統(tǒng)自動(dòng)開(kāi)辟蜒程、,釋放的绅你;一般存變量,函數(shù)的調(diào)用過(guò)程是在棧區(qū)間昭躺。
堆區(qū)間:從底層來(lái)看忌锯,由程序員自己開(kāi)辟的空間;一般存數(shù)據(jù)(python 中所有的數(shù)據(jù)都是對(duì)象)领炫。
從 python 的角度來(lái)看偶垮,程序員已經(jīng)不需要寫(xiě)代碼來(lái)開(kāi)辟空間和釋放空間了。
變量賦值過(guò)程:現(xiàn)在堆區(qū)間開(kāi)辟空間把數(shù)據(jù)存起來(lái)帝洪,然后將數(shù)據(jù)對(duì)應(yīng)的地址存到棧區(qū)間的變量中似舵。
注意:數(shù)字、字符串在賦值的時(shí)候葱峡,不會(huì)直接開(kāi)辟空間砚哗,會(huì)先檢測(cè)之前有沒(méi)有存儲(chǔ)過(guò)這個(gè)數(shù)據(jù),
如果有就用之前的數(shù)據(jù)地址砰奕。
2.內(nèi)存釋放(垃圾回收機(jī)制)原理:
python 中的每一個(gè)對(duì)象在創(chuàng)建的時(shí)候蛛芥,都有一個(gè)屬性,叫'引用計(jì)數(shù)',表示當(dāng)前對(duì)象的應(yīng)用個(gè)數(shù)脆淹。
判斷一個(gè)對(duì)象是否銷(xiāo)毀常空,就看'引用計(jì)數(shù)'是否為 0 ,為 0 就銷(xiāo)毀盖溺,否則不銷(xiāo)毀漓糙。
from sys import getrefcount (獲取對(duì)象的引用計(jì)數(shù))
例如:
from sys import getrefcount
def main():
list1 = [1, 2]
print(getrefcount(list1)) # 2
# 使用不同的變量存對(duì)象地址會(huì)增加引用計(jì)數(shù)
list2 = list1
print(getrefcount(list1)) # 3
[1, list1]
print(getrefcount(list1)) # 3
# def func1(obj):
# print(getrefcount(list1))
#
# func1(list1)
print(getrefcount(list1))
list1 = []
print(getrefcount(list2)) # 2
del list2
# print(getrefcount(list2)) # UnboundLocalError
# def getrefcount(obj):
# obj = list1
# 獲取obj的引用計(jì)數(shù)
bullets = [{'x': 10, 'y': 20}, {'x': 30, 'y': 10}, {'x': 100, 'y': 200}]
del bullets[2]
bullets.pop(0)
if __name__ == '__main__':
main()
運(yùn)行效果:
2
3
3
3
2