8. 類的成員描述符(屬性)
- 類的成員描述是為了在類中對類的成員屬性進(jìn)行相關(guān)操作而創(chuàng)建的一種方式
- get:獲取屬性的操作
- set:修改或添加屬性操作
- delete:刪除屬性的操作
- 如果想使用類的額成員描述符,大概有三種方法
- 使用類實(shí)現(xiàn)描述器
- 使用屬性修飾符
- 使用property函數(shù)
- property函數(shù)很簡單
- property(fget, fset, fdel, doc)
- 無論哪種修飾符都是為了對成員屬性進(jìn)行相應(yīng)的控制
- 類的方式:適用多個(gè)類中的多個(gè)屬性共用同一個(gè)描述符
- property:適用當(dāng)前類中使用,可以控制一個(gè)類中多個(gè)屬性
- 屬性修飾符:適用于當(dāng)前類中使用,控制一個(gè)類中的一個(gè)屬性
9. 類的內(nèi)置屬性
__dict__: 以字典的方式顯示類的成員組成
__doc__: 獲取類的文檔信息
__name__: 獲取類的名稱,如果在模塊中使用,獲取模塊的名稱
__bases__: 獲取某個(gè)類的所有父類,以元組的方式顯示
10. 類的常用魔術(shù)方法
- 魔術(shù)方法就是不需要人為調(diào)用的方法,基本是在特定的時(shí)間自動(dòng)觸發(fā)
- 魔術(shù)方法的統(tǒng)一特征,方法名被前后各兩個(gè)下劃線包裹
- 操作類
-
__init__:構(gòu)造函數(shù)
-
__new__:對象實(shí)例化方法,此魔術(shù)方法較特殊,一般不需要使用
-
__call__:對象當(dāng)函數(shù)使用的時(shí)候觸發(fā)
-
__str__:當(dāng)對象被當(dāng)作字符串使用的時(shí)候
-
__repr__:返回字符串
- 描述符相關(guān)
__set__
__get__
__delete__
- 屬性操作相關(guān)
-
__getattr__:訪問一個(gè)不存在的屬性時(shí)觸發(fā)
-
__setattr__:對成員屬性進(jìn)行設(shè)置的時(shí)候觸發(fā)
- 參數(shù):
- self用來獲取當(dāng)前對象
- 被設(shè)置的屬性名稱,以字符串形式出現(xiàn)
- 需要對屬性名稱設(shè)置的值
- 作用:進(jìn)行屬性設(shè)置的時(shí)候進(jìn)行驗(yàn)證或者修改
- 注意:在該方法中不能對屬性進(jìn)行賦值操作,否則死循環(huán)
- 運(yùn)算類相關(guān)魔術(shù)方法
-
__gt__:進(jìn)行大于判斷的時(shí)候觸發(fā)的函數(shù)
- 參數(shù)
- self
- 第二個(gè)參數(shù)是第二個(gè)對象
- 返回值可以是任意值,推薦返回布爾值
11. 類和對象的三種方法
- 實(shí)例方法
- 需要實(shí)例化對象才能使用的方法,使用過程中可能需要截至對象的其他對象的方法完成
- 靜態(tài)方法
- 類方法
# 屬性案例
# 創(chuàng)建Student類,描述學(xué)生類
# 學(xué)生具有Student.name屬性
# 但name格式并不統(tǒng)一
# 可以用增加一個(gè)函數(shù),然后自動(dòng)調(diào)用的方式,但很蠢
class Student():
def __init__(self, name, age):
self.name = name
self.age = age
# 如果不想修改代碼
self.setName(name)
# 介紹下自己
def intro(self):
print("Hai, my name is {0}".format(self.name))
def setName(self, name):
self.name = name.upper()
s1 = Student("RUO Chen", 19.8)
s2 = Student("michi stangle", 24.0)
s1.intro()
s2.intro()
Hai, my name is RUO CHEN
Hai, my name is MICHI STANGLE
# propertya 案例
# 定義一個(gè)Person類,具有name,age屬性
# 對于任意輸入的姓名,我們希望用大寫方式保存
# 年齡,我們希望內(nèi)部統(tǒng)一用整數(shù)保存
# x = property(fget, fset, fdel, doc)
class Person():
'''
這是一個(gè)人,一個(gè)高尚的人,一個(gè)脫離了低俗趣味的人
他還他媽的有屬性
'''
# 函數(shù)名稱可以任意
def fget(self):
return self._name * 2
def fset(self, name):
# 所有輸入的姓名以大寫方式 保存
self.name = name.upper()
def fdel(self):
self._name = "NoName"
name = property(fget, fset, fdel, "對name進(jìn)行操作")
# 類的內(nèi)置屬性舉例
print(Person.__dict__)
print(Person.__doc__)
print(Person.__name__)
# 元組形式顯示所有的父類
print(Person.__bases__)
{'__module__': '__main__', '__doc__': '\n 這是一個(gè)人,一個(gè)高尚的人,一個(gè)脫離了低俗趣味的人\n 他還他媽的有屬性\n ', 'fget': <function Person.fget at 0x000001FBBD3AFBF8>, 'fset': <function Person.fset at 0x000001FBBD3AF9D8>, 'fdel': <function Person.fdel at 0x000001FBBD3AF8C8>, 'name': <property object at 0x000001FBBD3B7BD8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
這是一個(gè)人,一個(gè)高尚的人,一個(gè)脫離了低俗趣味的人
他還他媽的有屬性
Person
(<class 'object'>,)
# init 舉例
class A():
def __init__(self, name = 0):
print("哈哈,我被調(diào)用了")
a = A()
哈哈,我被調(diào)用了
# __call__ 舉例
class A():
def __init__(self, name = 0):
print("哈哈,我被調(diào)用了")
def __call__(self):
print("我被調(diào)用again")
a = A()
a()
哈哈,我被調(diào)用了
我被調(diào)用again
# __str__ 舉例
class A():
def __init__(self, name = 0):
print("哈哈,我被調(diào)用了")
def __call__(self):
print("我被調(diào)用again")
def __str__(self):
return '666'
a = A()
print(a)
哈哈,我被調(diào)用了
666
# __getattr__
class A():
name = "NoName"
age = 18
def __getattr__(self, name):
print("沒找到")
print(name)
a = A()
print(a.name)
print(a.addr)
NoName
沒找到
addr
None
# __setattr__ 案例
class Person():
def __init__(self):
pass
def __setattr__(self, name, value):
print("設(shè)置屬性:{0}".format(name))
# 下面語句會(huì)導(dǎo)致問題,死循環(huán)
# self.name = value
# 此種情況,為了避免死循環(huán),規(guī)定統(tǒng)一調(diào)用父類魔法函數(shù)
super().__setattr__(name, value)
p = Person()
print(p.__dict__)
p.age = 18
{}
設(shè)置屬性:age
# __gt__
class Student():
def __init__(self, name):
self._name = name
def __gt__(self, obj):
print("哈哈,{0} 會(huì)比 {1} 大嗎?".format(self, obj))
return self._name > obj._name
stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
哈哈,<__main__.Student object at 0x000001C15772EB38> 會(huì)比 <__main__.Student object at 0x000001C15772E550> 大嗎?
False
# 三種方法的案例
class Person():
# 實(shí)例方法
def eat(self):
print(self)
print("Eating......")
# 類方法
# 類方法的第一個(gè)參數(shù),一般命名為cls,區(qū)別于self
@classmethod
def play(cls):
print(cls)
print("Playing......")
# 靜態(tài)方法
# 不需要用第一個(gè)參數(shù)表示自身或者類
@staticmethod
def say():
print("Saying......")
yueyue = Person()
# 實(shí)例方法
yueyue.eat()
# 類方法
Person.play()
yueyue.play()
# 靜態(tài)方法
Person.say()
yueyue.say()
<__main__.Person object at 0x000001C157766710>
Eating......
<class '__main__.Person'>
Playing......
<class '__main__.Person'>
Playing......
Saying......
Saying......