類的兩個裝飾器classmethod、staticethod和內置魔術方法
@classmethod:把類中的綁定方法變成一個類方法,cls 就等於類名
有什麼用?
1、在方法中任然可以引用類中的靜態變數
2、可以不用實例化對象,就直接用類名在外部調用這個方法
什麼時候用?
1、定義了一個方法,默認傳 self ,但這個 self 沒有被使用。
2、並且你在這個方法里用到了當前類名,或者你準備使用這個類的記憶體空間中的名字的時候
# 商品打折: class Goods: __discount = 0.8 def __init__(self, original_price): self.original_price = original_price self.price = self.original_price * self.__discount @classmethod # 把一個對象的綁定方法改成一個類方法 def change_discount(cls, count): cls.__discount = count # 相當於Goods.__discount = count Goods.change_discount(0.6) # 類方法可以通過類名調用 # 實例化一個華為手機對象 huawei = Goods(20) print(int(huawei.price)) huawei.change_discount(0.4) # 類方法可以通過對象調用 # 實例化一個蘋果手機對象 apple = Goods(20) print(int(apple.price)) # 輸出 12 8
擴展:
在掉用類的函數的時候就實例化了一個對象
import time class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def today(cls): structure = time.localtime() # 在方法中創建一個對象 obj = cls(structure.tm_year, structure.tm_mon, structure.tm_mday) return obj # 當調用類中的today方法就會返回一個對象(對象屬性不用自己填,today方法已經填好了) data對象 = Date.today() print(data對象.year) print(data對象.month) print(data對象.day) # 輸出 2021 5 4
@staticmethod:被裝飾的方法會成為一個靜態方法
本身是一個普通函數,被挪到類的內部執行,那麼直接給這個函數添加 @staticmethod 裝飾器就可以了
在函數的內部即用不到 self 變數,也用不到 cls 類
class User: pass @staticmethod def login(user): print(f'{user},登錄成功') User.login('Alen') # 類可以調佣 Bob = User() Bob.login('Bob') # 對象可以調佣 # 輸出 Alen,登錄成功 Bob,登錄成功
總結:能定義到類中的內容。
1、靜態變數:是個所有的對象共享的變數 ——由對象、類調用
2、實例變數:是對象的屬性變數 ——由對象調用
3、綁定方法:是個自帶self參數的函數 ——由對象調用
4、類方法:是個自帶cls參數的函數 ——由對象、類調用
5、property屬性:是個偽裝屬性的方法 ——由對象調用,但不加括弧
二、內置魔術方法
__call__
方法:對象 + ( ) 調用這個類中的__call__
方法
class User: pass @staticmethod def login(user): print(f'{user},登錄成功') User.login('Alen') # 類可以調佣 Bob = User() Bob.login('Bob') # 對象可以調佣 # 輸出 Alen,登錄成功 Bob,登錄成功
__len__
方法:len (對象) 需要實現這個類中的__len__
方法
class A: def __init__(self): self.lis = [1, 2, 3, 4, 5] def len(self): return len(self.lis) def __len__(self): return len(self.lis) a = A() print(len(a)) # 可以直接len(a)就可以查看lis裡面值的個數 print(a.len()) # 不然就要使用類中的len方法才可以查看 # 輸出 5 5 # ------------------------------------------------------------------------------------- # 擴展:也可以使用自定義的函數 class A: def __init__(self, count): self.count = count def __square__(self): value = self.count ** 2 return value def square(count): return A.__square__(count) a = A(5) print(square(a)) # 輸出 25
__new__
方法:實例化的時候會先執行__new__
方法用來創建一個對象需要的空間
class A: def __new__(cls, *args, **kwargs): o = super().__new__(cls) print(o) # 記憶體地址和 self 的記憶體地址一樣 print('執行了__new__方法') return o def __init__(self): print(self) print('執行了__init__方法') A() # 實例化對象 # 輸出 <__main__.A object at 0x014E0970> 執行了__new__方法 <__main__.A object at 0x014E0970> 執行了__init__方法
__new__
方法的設計模式:————>單例模式
一個類,從頭到尾,只會創建一次 self 的空間
class Car: __attribute = None def __new__(cls, *args, **kwargs): if cls.__attribute is None: # 當第一次開空間的時候__attribute肯定是空的 # 所以就會開一個新的空間。並把__attribute給賦值,那麼以後的都不是第一次了。 cls.__attribute = super().__new__(cls) return cls.__attribute # 把新空間返回給self def __init__(self, car_paint, cartwheel_colour): self.car_paint = car_paint self.cartwheel_colour = cartwheel_colour xiao_hong = Car('紅色的車漆', '藍色的車輪') print('小紅的記憶體地址:', xiao_hong) # 他們的記憶體地址都是一樣的 print(xiao_hong.car_paint) # 紅色的車漆————>小紅剛拿到的時候還是紅色的 xiao_ming = Car('白色的車漆', '黑色的車輪') print('小名的記憶體地址:', xiao_ming) print(xiao_hong.car_paint) # 白色的車漆————>小明在拿過來,把顏色給改成白的了 print(xiao_ming.car_paint) # 白色的車漆————>小紅的也變了,應為他們都是同一個車 # 輸出 小紅的記憶體地址: <__main__.Car object at 0x01A70A60> 紅色的車漆 小名的記憶體地址: <__main__.Car object at 0x01A70A60> 白色的車漆 白色的車漆
__str__
和__repr__
方法:
str方法:幫助我們在列印或展示對象的時候更加直觀的顯示對象內容
1、在列印一個對象的時候,調用__str__
方法
2、在 %s 拼接一個對象的時候,調用__str__
方法
3、在str一個對象的時候,調用__str__
方法
當列印一個對象的時候,希望這個對象顯示的值是什麼,那麼你就必須在這個對象內部實現一個__str__
,這樣的話你就能做到,你在列印這個對象的時候你就能查看到他的內容是多少(查看的內容由你自己在 str 中定義),不然就只能答應一堆記憶體地址。
repr方法:是 str 的備胎(有str的時候列印str,沒有就列印rper),同時 %r 和 repr 有合作關係
class User: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return self.name def __repr__(self): return self.age Bob = User('鮑勃', '18') print(Bob) # 現在就可以直接列印對象了,——不設置str方法,列印的就是是一堆記憶體地址,優先列印 str 方法 print('我的名字是%s' % Bob) # 在 %s 拼接一個對象的時候,調用__str__方法 print('我的年齡是%r' % Bob) # 在 %r 拼接一個對象的時候,調用__repr__方法 # 輸出 鮑勃 我的名字是鮑勃 我的年齡是18