函數裝飾器
對於某個函數,如果我們希望在不改變該函數代碼的前提下,爲該函數增加額外的功能,那麼就可以使用裝飾器來裝飾該函數。
裝飾器是一個函數,裝飾器接收一個函數作爲參數(傳入的實參是被裝飾的函數)
裝飾器的內部嵌套定義另一個函數,內函數中會引用裝飾器的參數,並且裝飾器的返回值是內函數。
爲了讓內函數接收任意類型的參數,將內函數的形參定義爲(*args,**kwargs)
在函數中,首先完成爲被裝飾函數添加的新功能,然後調用被裝飾的函數。
把裝飾器應用到被裝飾函數的語法爲:在被裝飾函數的前面添加“@裝飾器的函數名”
def notice(func):
def wrapper(*args,**kwargs):
print("公告:注意身體!")
return func(*args,**kwargs)
return wrapper
@notice
def add(a,b):
return a + b
@notice
def subt(a,b):
return a - b
print(add(3,5))
>公告:注意身體!
8
print(subt(8,3))
>公告:注意身體!
5
類方法
類方法指的是類對象中使用裝飾器@classmethod進行裝飾的方法
在類對象中定義類方法時,必須使用裝飾器@classmethod進行裝飾,此外,第一個形參表示類對象,其對應的實參由系統自動傳入。第一個形參的名稱通常是cls。
類對象可以被類對象所調用,語法格式爲:類對象.方法名([實參])或:cls.方法名([實參])。
類對象也可以實例對象所調用,語法格式爲:實例對象.方法名([實參])或:self.方法名([實參])。
class MyClass(object):
#在類對象中定義類方法
@classmethod
def class_func(cls,a,b):
print(a,b)
#通過類對象調用類方法
MyClass.class_func('hi','hello!')
>hi hello!
#通過實例對象調用類方法
mc = MyClass
mc.class_func(1,2)
>1 2
PS:可以用實例對象調用類方法,但是不能用類對象調用實例方法
靜態方法
類對象的靜態方法只是一個普通函數,把某個普通函數歸屬於類對象,可能只是爲了易於代碼管理。在類對象中定義靜態方法時,必須使用裝飾器@staticmethod進行裝飾
靜態方法 只是一個普通函數,因此,第一個形參沒有特殊含義和要求。
靜態方法可以被類對象所調用,語法格式爲:類對象.方法名([實參])或:cls.方法名([實參])。
靜態方法也可以實例對象所調用,語法格式爲:實例對象.方法名([實參])或:self.方法名([實參])。
調用靜態方法時的參數傳遞與調用普通函數是一樣的。
class MyClass(object):
@staticmethod
def sm(p1,p2):
print(p1,p2)
MyClass.sm(1,2)
>1 2
mc = MyClass()
mc.sm(1,2)
>1 2
訪問控制
訪問控制指的是:控制類對象的屬性和方法在類對象的外部是否可以直接訪問。
如果在類對象的某個屬性或方法前添加兩個下劃線__,那麼在類對象的外部就不能直接訪問該屬性或方法了。
class MyClass(object):
def __init__(self):
self.__pia = 18
def __pim(self):
print("__pim()被調用了")
mc = MyClass()
print(mc.__pia)
>#報錯
>---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-229fd1431afb> in <module>()
5 print("__pim()被調用了")
6 mc = MyClass()
----> 7 print(mc.__pia)
AttributeError: 'MyClass' object has no attribute '__pia'
mc.__pia()
>#報錯
>---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-a65b2ec13347> in <module>()
----> 1 mc.__pia()
AttributeError: 'MyClass' object has no attribute '__pia'
print(mc._MyClass__pia)
>18
mc._MyClass__pim()
>__pim()被調用了
仍然可以在類對象的外部動態綁定名爲__xxx的屬性或方法,這與類對象內部名爲__xxx的屬性或方法是不同的。
mc.__pia = "hi"
print(mc.__pia)
>hi
print(dir(mc))
>['_MyClass__pia', '_MyClass__pim', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__pia', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'do_sth']
除了在類對象的屬性或方法前添加兩個下劃線__,還可以在類對象的屬性或方式前添加單下劃線_,這表示:雖然可以在類對象的外部訪問該屬性或方法,但是最好不要訪問。