1.內(nèi)置類屬性
內(nèi)置類屬性就是魔法屬性
魔法屬性:屬性名的前面和后面都有兩個下劃線
魔法方法:方法的前后都有兩個下劃線
import datetime
class Person:
"""人類"""
number = 61 #類的字段
def __init__(self,name1,age1,height1):
self.name = name1
self.age = age1
self.height = height1
def run(self):
print("%s在跑步" % self.name)
#類方法
@classmethod
def show_number(cls):
print("人類的數(shù)量為:%億" % cls.number)
#靜態(tài)方法
@staticmethod
def destroy():
print("人類在破壞環(huán)境")
p1 = Person("張三",25,175)
1.name屬性
name = Person.__name__
print(name,type(name))
2._classs屬性
對象的屬性,
my_class是一個類,之前類能做的事他都能做
my_class = p1.__class__
p2 = my_class("小明",20,175)
dict屬性---將對象屬性及其對應(yīng)的值裝換成鍵值對存到一個字典中
print((Person.__dict__))
4.doc屬性--->獲取類的說明文檔
類的屬性
doc= Person.__doc__
print(doc)
5.module屬性---獲取類所在的模塊對應(yīng)的名字
print(Person.__module__)
print(datetime.datetime.__module__)
6.base屬性 --獲取當前類的父類
print(Person.__bases__)
2.slots魔法
通過solts中存的元素的屬性的值來約束當前這個類的對象的屬性
對象的屬性只能比元組中的元素少,不能多
class Person:
__slots__ = ("name","age","face")
def __init__(self):
self.name = "張三"
self.age = 20
self.face = 70
#self.sex = "boy" #__slots__中并沒有sex
p1 = Person()
# p1.sex = "girl"
# print(p1.sex)
#
# p1.name = "小明"
print(p1.name)
注意,一旦在類中給slots屬性賦了值,那么這個類的對象的dict屬性就不能用了
3.屬性的私有化
python中并沒有真正的私有化
1.私有化
a.類中的屬性和方法都可以通過在屬性名和方法名前加兩個下劃線,來讓屬性和方法變成私有的
b.私有的屬性和方法只能在當前的類中使用
2.私有化原理
在前面有兩個下劃線的屬性名和方法名前添加了"_類名"來阻止外部通過直接訪問屬性名來使用屬性
class Dog:
#字段
number = 100
__count = 200
def __init__(self):
#對象的屬性
self.color = "黃色"
self.age = 3
self.name = "大黃"
self.sex = "boy"
#對象方法
def eat(self):
#在類中可以使用屬性的私有化
# self.__eat()
print("%s在啃骨頭" % self.name)
#類方法
@classmethod
def shout(cls):
print("count:",cls.__count,Dog.__count)
print("汪 汪汪")
#靜態(tài)方法
@staticmethod
def function():
print("看家")
#python的類中默認的屬性和方法都是公開的
dog1 = Dog()
print(Dog.number)
print(dog1.name,dog1.age,dog1.color)
dog1.eat()
dog1.shout()
dog1.function()
#在類的外面不能使用屬性的私有化
#print(Dog.__count)
# print(dog1.__sex)
# dog1.__eat()
print(dog1._Dog__sex)
print(dog1.__dict__)
#在類的外面不能使用屬性的私有化
#print(Dog.__count)
# print(dog1.__sex)
# dog1.__eat()
print(dog1._Dog__sex)
print(dog1.__dict__)
輸出:
100
大黃 黃色 3
大黃啃骨頭~
大黃在吃屎~
count: 200 200
汪汪汪~~~
看家!!
公狗
{'color': '黃色', 'age': 3, 'name': '大黃', '_Dog__sex': '公狗'}
4.屬性的getter和setter
1.保護類型的屬性:
a.就是在聲明對象屬性的時候在屬性名前加一個下劃線來代表這個屬性是受保護的屬性,那么以后訪問這個屬性的時候就不要直接訪問,要通過getter來獲取這個屬性的值,setter來給這個屬性賦值
b.如果一個屬性已經(jīng)聲明成保護類型的屬性,那么我們需要給這個屬性添加getter,也可以添加setter
2.添加getter
添加getter其實就是聲明一個沒有返回值的函數(shù)
a.聲明的格式:
@property
def 去掉下劃線的屬性名(self)
函數(shù)體
將屬性相關(guān)的值返回
b.使用場景
1.如果想要在獲取對象的某個屬性的值前,想要再做點別的事情,就可以給這個屬性添加getter
2.想要拿到某個屬性被使用的時刻
3.添加setter
添加setter就是聲明一個有一個參數(shù)但是沒有返回值的函數(shù),作用是給屬性賦值
class Car:
def __init__(self):
self.color = "黃色"
self.type = "自行車"
#_price是保護類型
self._price = 1000
#給_price屬性添加getter
@property
def price(self):
print("保護屬性")
return self._price/1000
#想要給一個屬性添加setter必須先給這個屬性添加getter
@price.setter
def price(self,price):
if isinstance(price,int) or isinstance(price,float):
self._price = price
else:
self.price = 0
car1 = Car()
print(car1.color,car1._price)
#添加完getter后就通過getter去獲取屬性的值
#price就是_price的getter
print(car1.price,"k") #實質(zhì)是在調(diào)用getter對應(yīng)的方法
#通過setter給_price屬性賦值,實質(zhì)是在調(diào)用setter對應(yīng)的方法
car1.price = 3000
print(car1.price)
輸出:
黃色 1000
保護屬性
1.0 k
保護屬性
3.0
保護屬性
0.0
練習(xí):聲明一個員工類,其中有一個屬性是是否已婚(bool)獲取值之前根據(jù)存的值返回"已婚/未婚"
class Staff:
def __init__(self,name,age):
self.name = name
self.age = age
self._is_married = False
@property
def is_married(self):
if self._is_married:
return "已婚"
else:
return "未婚"
@is_married.setter
def is_married(self,married):
self._is_married = married
staff1 = Staff("咻咻",23)
print(staff1.is_married)
staff1.is_married = True
print(staff1.is_married)
輸出:
未婚
已婚
5.繼承
python中的類可以繼承,并且支持多繼承
程序中的繼承:就是讓子類直接擁有父類的屬性和方法,(繼承后父類中的內(nèi)容不會因為繼承而減少)
1.繼承的語法
class 子類(父類)
類的內(nèi)容
注意:如果生命類的時候沒有寫繼承,那么這個類會自動繼承python的基類object;相當于class類名(object)
python中所有的類都是直接或者間接的繼承自object
2.能繼承哪些東西
a.所有的屬性和方法都能繼承
b.slots的值不會繼承,但是會影響子類對象的dict屬性,不能獲取到父類繼承下來的屬性
class Person:
"""人類"""
#字段
number = 1000
# __slots__ = ("name","age")
#對象屬性
def __init__(self,name = "biubiu",age = 20):
self.name = name
self.age = age
self._height = 159
#對象方法
def show_massage(self):
print("姓名:%s 年齡:%d" % (self.name,self.age))
#類方法
@classmethod
def show_number(cls):
print("人類數(shù)量:%d" % cls.number)
#靜態(tài)方法
@staticmethod
def complaint():
print("弄死?。?)
class Student(Person):
"""學(xué)生類"""
pass
#創(chuàng)建Person類的對象
#創(chuàng)建Student類的對象
stu1 = Student()
print(Student.number)
stu1.name = "咻咻"
print(stu1.name)
stu1.show_massage()
Student.show_number()
Student.complaint()
stu1.sex = "girl"
print(stu1.__dict__)
6.方法的重寫
子類繼承父類,擁有父類的屬性和方法以后,還可以再添加自己的屬性和方法
1.添加方法和類的字段
直接在子類中聲明相應(yīng)的方法和字段
2.添加對象屬性
對象的屬性是通過繼承父類的init方法而繼承下來
如果想要在保留父類的對象的同時添加自己的對象屬性,需要在子類的init方法中通過super()去調(diào)用父類的init方法
3.方法的重寫
在子類中重新實現(xiàn)父類的方法,就是重寫
方式一: 直接覆蓋父類的實現(xiàn)
方式二: 保留父類的功能再添加其他功能
4.類中方法的調(diào)用過程(重點)
先在當前這個中的去找,沒有去父類中找,找不到再去父類的父類中找,依次類推,如在基類中都沒有找到才崩潰。
在第一次找到的位置,去調(diào)用
注意:使用super的時候必須是通過super()來代替父類或者是父類對象
class Animal:
def __init__(self):
self.age = 1
self.sex = "雌"
def shout(self):
print("嗷嗚~~")
def eat(self):
print("吃")
class Cat(Animal):
def __init__(self):
#調(diào)用父類的init方法
super().__init__()
self.name = "小花"
food = "魚"
def shout(self):
print("妙?。?!")
class Dog(Animal):
def shout(self):
#通過super()調(diào)用父類的方法,保留父類的功能
super().shout()
print("汪 汪汪")
cat1 = Cat()
cat1.shout()
print(cat1.name)
print(cat1.age)
dog1 = Dog()
dog1.shout()
7.init方法的重寫
練習(xí),寫一個Person類,擁有屬性name,age,sex,要求創(chuàng)建Person對象的時候必須給name和age賦值,sex可賦可不賦
再寫一個Staff類繼承自Person類,要求保留Person中所有的屬性,并且添加新的屬性salary
要求創(chuàng)建Staff類對象的時候,只能給name賦值(必須賦)
class Person:
def __init__(self,name,age,sex = "girl"):
self.name = name
self.age = age
self.sex = sex
class Staff(Person):
def __init__(self,name):
super().__init__(name,20)
self.salary = 8000
p1 = Person("秀秀",21)
p2 = Person("啾啾",23,"男")
s1 = Staff("咻咻")
8.運算符的重載
如果希望類的對象支持相應(yīng)的運算符操作(例如:+, -, *, /, >, <等),就必須實現(xiàn)相應(yīng)的魔法方法。
這個過程就叫運算符的重載
一般情況需要對>或者<進行重載,重載后可以通過sort方法直接對對象的列表進行排序
class Student:
def __init__(self, name='', age=0, score=0):
self.name = name
self.age = age
self.score = score
# self:+前面的對象
# other: +后面的對象
def __add__(self, other):
return self.score + other.score
# 重載 > 符號
# 注意:重載>和<可以只重載一個,另外一個對應(yīng)的功能自動取反
def __gt__(self, other):
return self.age > other.age
# 重寫魔法方法__str__,用來定制對象的打印樣式
def __str__(self):
# return '<%s.%s object at 0x%x>' % (self.__module__, self.__class__.__name__, id(self))
# return 'Student: %s %d %d' % (self.name, self.age, self.score)
return str(self.__dict__)[1:-1]
class Schoolchild(Student):
def __add__(self, other):
return self.age + other.age
if __name__ == '__main__':
stu1 = Student('小明', 18, 90)
stu2 = Student('老王', 29, 84)
stu3 = Student('小花', 20, 78)
print(stu1)
all_students = [stu1, stu2, stu3]
all_students.sort(reverse=True)
for stu in all_students:
print(stu.name, stu.age, stu.score)
print(stu1 > stu2)
print(stu1 < stu2)
print(stu1 + stu2)
print(stu3 > stu1)
# 父類重載了運算符,子類也能用
c1 = Schoolchild('小明明', 8, 70)
c2 = Schoolchild('小花花', 10, 67)
print(c1+c2)
輸出:
'name': '小明', 'age': 18, 'score': 90
老王 29 84
小花 20 78
小明 18 90
False
True
174
True
18