Python基礎(二十一):面向對象「類」第四課——魔法方法

先劃一下重點:python

  • 6個魔法方法;
  • 動態操做屬性的4個函數;

魔法方法

魔法方法的簡單介紹

  • 魔法方法的命名規則:方法名(先後各有2個下劃線)。函數

  • 一般狀況下,不會主動去調用魔法方法,而是在知足必定的條件下,會自動去調用魔法方法。3d

  • 經常使用的魔法方法有6個,分別是:new、del、str、repr、bytes、call,下面我爲你們一一講解。code

new方法

  • 注意1 :在建立對象的時候,會首先調用該方法,init方法仍是在 new方法以後被調用;
  • 注意2 :一個不須要@classmethod修飾的類方法;
  • 注意3 :咱們只須要知道,在建立對象的時候,new方法比init方法,先調用便可。平時沒怎麼用它;
class Person:
	# __new__不用@classmethod修飾的一個類方法
	# 在建立對象的時候,會首先調用該方法
	# 若是在該方法中,返回當前類的對象(也即建立對象),接下來會調用__init__方法,對對象進行初始化。不然,__init__方法不會獲得執行
	def __new__(cls):
		return super().__new__(cls)  # 這行代碼是建立對象,只是我如今不太明白


Person()  # 在咱們寫類的時候,不須要寫這個。這裏講述一下,只是想讓咱們知道。在建立對象的時候,__new__方法比__init__方法,先調用

若一個類中既有new方法,也有init方法,當咱們建立對象時候,首先執行new方法。orm

假如,new方法中沒有return super().new(cls) ,則不會執行init方法。寫上之後,表示再次建立一個對象纔會執行init方法。對象

# 第一段代碼
class Person:
	def __new__(cls):
		print("__new__執行")
		return super().__new__(cls)  # 這行代碼是建立對象,只是我如今不太明白

	def __init__(self):
		print("__init__執行")


p = Person()


# 第二段代碼
class Person:
	def __new__(cls):
		print("__new__執行")
		# return super().__new__(cls)   # 假如不返回,當前類的對象,__init__就不會執行
		
	def __init__(self):
		print("__init__執行")


p = Person()  # 由於,這裏建立的對象,先去執行new方法了

結果以下:blog

del方法

在銷燬對象的時候(對象指的是咱們本身建立的對象),會首先調用該方法。字符串

class Person:
    def __init__(self):
        print("__init__執行")
    # 在該方法中,能夠執行一些清理工做
    def __del__(self):
        print("該對象已經被銷燬")

p = Person() # 能夠看出,由於沒有對象銷燬,因此不會調用該方法

結果以下:get

class Person:
    def __init__(self):
        print("__init__執行")
    def __del__(self):
        print("該對象已經被銷燬")
p = Person()
del p

結果以下:input

str方法

  • 注意1 :該方法在使用內建函數(str,format,print)的時候,會自動調用;
  • 注意2 :該方法末尾,須要返回一個str類型的對象;
class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    def __del__(self):
        print("該對象已經被銷燬")
    # 在使用內建函數(str,format,print)的時候,會自動調用該方法
    # 該方法須要返回一個str類型的對象
#     def __str__(self):
#         return "Person類型的對象"
p = Person()
print(p)

結果以下:

class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    # 在使用內建函數(str,format,print)的時候,會自動調用該方法
    # 該方法須要返回一個str類型的對象
    def __str__(self):
        return "Person類型的對象"

p = Person()
p

結果以下:

class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    # 在使用內建函數(str,format,print)的時候,會自動調用該方法
    # 該方法須要返回一個str類型的對象
    def __str__(self):
        return "Person類型的對象"

p = Person()
print(p)

結果以下:

repr方法

  • 注意1 :該方法在使用內建函數(repr)的時候,會自動調用;
  • 注意2 :該方法也須要返回一個str類型的對象;
class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    def __del__(self):
        print("該對象已經被銷燬")
    def __str__(self):
        return "Person類型的對象"
    # __str__ 與 __repr__ 的區別:兩者都是返回對象的字符串表示。
    # 不一樣的是:__str__ 返回的一般是讓人容易閱讀的格式。__repr__返回的是面向Python解釋器的,一般格式:<內容>
    def __repr__(self):
        return "<Person class>"

p = Person()
print(str("abc"))  # 結果是abc,這個更加接近人閱讀模式
print(repr("abc")) # 結果是'abc',字符串原本就是帶引號的,因此這個和python解釋器更相近

結果以下:

bytes方法

該方法在使用內建函數(bytes)的時候,會自動調用.

class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    def __del__(self):
        print("該對象已經被銷燬")
    def __str__(self):
        return "Person類型的對象"
    def __repr__(self):
        return "<Person class>"
    def __bytes__(self):
        return b"byte person class"

p = Person()
print(bytes(p))

結果以下:

call方法

把對象當成函數來使用的時候,會自動調用。

class Person:
    def __new__(cls):
        print("__new__執行")
        return super().__new__(cls)
    def __init__(self):
        print("__init__執行")
    def __del__(self):
        print("該對象已經被銷燬")
    def __str__(self):
        return "Person類型的對象"
    def __repr__(self):
        return "<Person class>"
    def __bytes__(self):
        return b"byte person class"
    # 把對象當成函數來使用的時候,會自動調用該方法
    def __call__(self):
        print("把對象當成函數來使用的時候")

p = Person()
p()

結果以下:

動態操做屬性的4個函數

這4個函數分別是:hasattr、getattr、delattr、setattr,下面咱們一一來說述。

hasattr(參數1,參數2)

  • 第一個參數 :對象;
  • 第二個參數 :屬性名;
  • 含義:判斷某個對象,是否存在指定的屬性名。若是存在,返回True,不然,返回False;
class Person():
    pass
    
p = Person()
print(hasattr(p,"name"))
p.name = "3417"
print(hasattr(p,"name"))

結果以下:

getattr(參數1,參數2,參數3)

  • 第一個參數 :對象;
  • 第二個參數 :屬性名;
  • 第三個參數 :當屬性不存在時,返回默認值,這個默認值也是本身設置;
  • 含義:返回對象對應的屬性(第二個參數指定的屬性)。傳入2個參數,若不存在,則報錯;穿入3個參數,若不存在,返回第三個參數設置的默認值;
class Person():
	pass


p = Person()
print(getattr(p, "name"))

結果以下:

class Person():
	pass


p = Person()
p.name = "關注一波?"
print(getattr(p, "name"))

結果以下:

class Person():
    pass
    
p = Person()
print(getattr(p,"age","沒有屬性返回的默認值"))

結果以下:

setattr(參數1,參數2,參數3)

  • 第一個參數:對象;
  • 第二個參數:屬性名;
  • 第三個參數:屬性值;
  • setattr(p,"age",20) 至關於 p.age = 20;
class Person():
    pass
    
p = Person()
setattr(p,"age",20)
print(p.age)

結果以下:

delattr(參數1,參數2,參數3)

  • 第一個參數:對象;
  • 第二個參數:屬性名;
  • delattr(p,"name") 至關於 del p.name;
class Person():
    pass
    
p = Person()
setattr(p,"age",20)
delattr(p,"age")
print(hasattr(p,"age"))

結果以下:

注意1 :動態操做屬性沒有直接操做屬性簡便,可是比直接訪問屬性靈活。

注意2 :直接訪問屬性必須在寫代碼時,就須要知道屬性的名字,而動態操做屬性沒有此限制(這在其餘語言中叫作'"反射")。

class Person():
	pass


p = Person()
unknown = input("請輸入屬性名:")
value = input("請輸入屬性值:")
setattr(p, unknown, value)
print(getattr(p, unknown))

結果以下:

相關文章
相關標籤/搜索