@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