靜態方法、類方法、屬性方法


一、靜態方法

 1.1、定義

   在類中的方法前面通過@staticmethod裝飾器即可把其裝飾的方法變為一個靜態方法

class Person(object):

    def __init__(self, name):
        self.name = name

    @staticmethod
    def speak():
        print('someone is speaking chinese.')

# 靜態方法在類中也不需要傳入 self參數

  

1.2、靜態方法的特性

  靜態方法是不能訪問實例變量和類變量的 

class Person(object):

    def __init__(self, name):
        self.name = name

    @staticmethod
    def speak(self):
        print('%s is speaking chinese.' % self.name)

p = Person('Bigberg')
p.speak()


# 我們在 speak(self) 函數中傳入 self

  事實上以上代碼運行會出錯的,說speak 需要一個self參數,但調用時卻沒有傳遞,沒錯,當speak變成靜態方法后,再通過實例調用時就不會自動把實例本身當作一個參數傳給self了。  

Traceback (most recent call last):
  File "G:/python/untitled/study6/靜態方法.py", line 26, in <module>
    p.speak()
TypeError: speak() missing 1 required positional argument: 'self'

  想讓以上代碼可以正常執行,有兩種方法:

  1. 在調用時將實例本身傳給 speak() 
class Person(object):

    def __init__(self, name):
        self.name = name

    @staticmethod
    def speak(self):
        print('%s is speaking chinese.' % self.name)

p = Person('Bigberg')
p.speak(p)

# 輸出

Bigberg is speaking chinese.

  2.在方法speak中去掉self,但這也意味着,在eat中不能通過self.調用實例中的其它變量了 

class Person(object):

    def __init__(self, name):
        self.name = name

    @staticmethod
    def speak():                # 方法中已經沒有 self 參數了
        print('%s is speaking chinese.' % 'anyone')

p = Person('Bigberg')
p.speak()


#輸出
anyone is speaking chinese.

  

1.3 總結

  普通的方法,可以在實例化后直接調用,並且在方法里可以通過self.調用實例變量或類變量,但靜態方法是不可以訪問實例變量或類變量的,一個不能訪問實例變量和類變量的方法,其實相當於跟類本身已經沒什么關系了,它與類唯一的關聯就是需要通過類名來調用這個方法。

 

二、類方法

  2.1、定義

  類方法通過@classmethod裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量

  2.2、訪問實例變量

        直接訪問實例變量會報錯,沒有該屬性  

class Person(object):

    def __init__(self, name, country):
        self.name = name
        self.country = country

    @classmethod
    def nationality(self):
        print('Bigberg is %s.' % self.country)

p = Person('Bigberg', 'CN')
p.nationality()

# 輸出
Traceback (most recent call last):
  File "G:/python/untitled/study6/靜態方法.py", line 31, in <module>
    p.nationality()
  File "G:/python/untitled/study6/靜態方法.py", line 24, in nationality
    print('Bigberg is %s.' % self.country)
AttributeError: type object 'Person' has no attribute 'country'

# 提示沒有一個 country 屬性  

  2.3、訪問類變量,即 全局屬性/靜態字段 

class Person(object):

    country = 'Chinese'    # 增加一個 全局屬性/靜態字段

    def __init__(self, name, country):

        self.name = name
        self.country = country

    @classmethod
    def nationality(cls):    # 這里將sefl 改為 cls
        print('Bigberg is %s.' % cls.country)

p = Person('Bigberg', 'CN')
p.nationality()

# 輸出
Bigberg is Chinese.

 

三、屬性方法 

   3.1、定義

  屬性方法的作用就是通過@property把一個方法變成一個靜態屬性 

class Person(object):

    country = 'Chinese'

    def __init__(self, name, country):

        self.name = name
        self.country = country

    @property
    def drive(self):
        print('%s is driving a car.' % self.name)
p = Person('Bigberg', 'CN')
p.drive()
# 輸出 
Traceback (most recent call last): Bigberg is driving a car. File "G:/python/untitled/study6/靜態方法.py", line 38, in <module> p.drive() TypeError: 'NoneType' object is not callable

  調用會出錯誤, 說NoneType is not callable, 因為eat此時已經變成一個靜態屬性了, 不是方法了, 想調用已經不需要加()號了,直接p.drive就可以了

  正常調用: 

p = Person('Bigberg', 'CN')
p.drive

# 輸出

Bigberg is driving a car.

  

  3.2 setter用法

  如果我們想在屬性方法里傳參,比如車的品牌,我們就要用setter了,具體用法  @屬性方法名.setter 

class Person(object):

    country = 'Chinese'

    def __init__(self, name, country):

        self.name = name
        self.country = country
        self.car = "LAMBORGHINI"   # 定義車品牌為蘭博基尼

    @property
    def drive(self):
        print('%s is driving a %s.' % (self.name, self.car))

p = Person('Bigberg', 'CN')
p.drive

# 輸出
Bigberg is driving a LAMBORGHINI.

  很顯然我們開出去的車就是蘭博基尼,如果我們想自己傳入車品牌呢?比如 特斯拉: 

class Person(object):

    country = 'Chinese'

    def __init__(self, name, country):

        self.name = name
        self.country = country
        self.car = "LAMBORGHINI"   #當然這里也可以設置為私有屬性

    @property
    def drive(self):  # 這里不能傳參是因為調用的時候,p.drive 沒有()了,不能傳入
        print('%s is driving a %s.' % (self.name, self.car))

    @drive.setter     # 修飾方法drive,可以為屬性賦值
    def drive(self, car):     # 我們要重新定義這個drive方法
        print("set car:", car)
        self.car = car

p = Person('Bigberg', 'CN')
p.drive = 'Tesla'     # 給屬性賦值
p.drive

#輸出

set car: Tesla
Bigberg is driving a Tesla.

  3.3 deleter 用法

  用來刪除屬性方法,具體用法 @屬性方法名.deleter  

# 以上例
# 我們可以發現普通屬性是可以通過del直接刪除的
# 比如
print(p.name)
del p.name
print(p.name)

# 輸出

Traceback (most recent call last):
Bigberg
  File "G:/python/untitled/study6/靜態方法.py", line 49, in <module>
    print(p.name)
AttributeError: 'Person' object has no attribute 'name'

#刪除之后就不能再調用了

  但是我們用del p.drive這種方法來刪除屬性方法是行不通的:

del p.drive

#輸出
Traceback (most recent call last):
  File "G:/python/untitled/study6/靜態方法.py", line 51, in <module>
    del p.drive
AttributeError: can't delete attribute

  所以我們就要用到 deleter方法: 

class Person(object):

    country = 'Chinese'

    def __init__(self, name, country):

        self.name = name
        self.country = country
        self.car = "LAMBORGHINI"

    @property
    def drive(self):
        print('%s is driving a %s.' % (self.name, self.car))

    @drive.setter
    def drive(self, car):
        print("set car:", car)
        self.car = car

    @drive.deleter   # 修飾 drive 方法,可以刪除屬性
    def drive(self):   # 重新定義 drive方法
        del self.car    #  刪除的是屬性
        print("扣了你的車,讓你開豪車...")

p.drive = 'Tesla'
p.drive

del p.drive   

# 輸出
set car: Tesla
Bigberg is driving a Tesla.
扣了你的車,讓你開豪車...

  讓我們在秋名山再開一次車...

p.drive

# 輸出
扣了你的車,讓你開豪車...
Traceback (most recent call last):
  File "G:/python/untitled/study6/靜態方法.py", line 57, in <module>
    p.drive
  File "G:/python/untitled/study6/靜態方法.py", line 28, in drive
    print('%s is driving a %s.' % (self.name, self.car))
AttributeError: 'Person' object has no attribute 'car'

# 提示沒有這個屬性了

 

四、屬性方法應用場景

你想知道一個航班當前的狀態,是到達了、延遲了、取消了、還是已經飛走了, 想知道這種狀態你必須經歷以下幾步:

1. 連接航空公司API查詢

2. 對查詢結果進行解析 

3. 返回結果給你的用戶

因此這個status屬性的值是一系列動作后才得到的結果,所以你每次調用時,其實它都要經過一系列的動作才返回你結果,但這些動作過程不需要用戶關心,用戶只要知道結果就行

class Flight(object):

    def __init__(self, name):
        self.name = name

    def check_status(self):
        print("checking flight %s status" % self.name)
        return 1

    @property
    def flight_status(self):
        status = self.check_status()
        if status == 0:
            print("flight got canceled...")

        elif status == 1:
            print("flight is arrived...")

        elif status == 2:
            print("flight has departured already...")

        else:
            print("cannot confirm the flight status")

    @flight_status.setter
    def flight_status(self, status):
        status_dic = {
            0: "canceled",
            1: "arrived",
            2: "departured"
        }
        print("\033[31;1mHas changed the flight status to \033[0m", status_dic.get(status))

    @flight_status.deleter  # 刪除
    def flight_status(self):
        print("status got removed...")

f = Flight('CA980')
f.flight_status 
f.flight_status = 2

#輸出

checking flight CA980 status
flight is arrived...
Has changed the flight status to  departured

  

五、總結

  1.  靜態方法是不可以訪問實例變量或類變量的
  2. 類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量
  3. 屬性方法將一個方法變為類的屬性,調用時不需要加()。有@property 、@屬性方法名.setter、@屬性方法名.deleter 三種裝飾方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM