1. 程式人生 > >靜態方法,類方法,屬性,setter用法,delete用法和屬性方法的應用場景

靜態方法,類方法,屬性,setter用法,delete用法和屬性方法的應用場景

一、靜態方法

 1.1、定義

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

1

2

3

4

5

6

7

8

9

10

class Person(object):

 

    def __init__(self, name):

        self.name = name

 

    

@staticmethod

    def speak():

        print('someone is speaking chinese.')

 

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

  

1.2、靜態方法的特性

  靜態方法是不能訪問例項變數和類變數的 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

class Person(

object):

 

    def __init__(self, name):

        self.name = name

 

    @staticmethod

    def speak(self):

        print('%s is speaking chinese.'

 % self.name)

 

= Person('Bigberg')

p.speak()

 

 

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

  事實上以上程式碼執行會出錯的,說speak 需要一個self引數,但呼叫時卻沒有傳遞,沒錯,當speak變成靜態方法後,再通過例項呼叫時就不會自動把例項本身當作一個引數傳給self了。  

1

2

3

4

Traceback (most recent call last):

  File "G:/python/untitled/study6/靜態方法.py", line 26in <module>

    p.speak()

TypeError: speak() missing 1 required positional argument: 'self'

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

  1. 在呼叫時將例項本身傳給 speak() 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class Person(object):

 

    def __init__(self, name):

        self.name = name

 

    @staticmethod

    def speak(self):

        print('%s is speaking chinese.' % self.name)

 

= Person('Bigberg')

p.speak(p)

 

# 輸出

 

Bigberg is speaking chinese.

  2.在方法speak中去掉self,但這也意味著,在eat中不能通過self.呼叫例項中的其它變量了 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

class Person(object):

 

    def __init__(self, name):

        self.name = name

 

    @staticmethod

    def speak():                # 方法中已經沒有 self 引數了

        print('%s is speaking chinese.' % 'anyone')

 

= Person('Bigberg')

p.speak()

 

 

#輸出

anyone is speaking chinese.

  

1.3 總結

  普通的方法,可以在例項化後直接呼叫,並且在方法裡可以通過self.呼叫例項變數或類變數,但靜態方法是不可以訪問例項變數或類變數的,一個不能訪問例項變數和類變數的方法,其實相當於跟類本身已經沒什麼關係了,它與類唯一的關聯就是需要通過類名來呼叫這個方法。

 

回到頂部

二、類方法

  2.1、定義

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

  2.2、訪問例項變數

        直接訪問例項變數會報錯,沒有該屬性  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

class Person(object):

 

    def __init__(self, name, country):

        self.name = name

        self.country = country

 

    @classmethod

    def nationality(self):

        print('Bigberg is %s.' % self.country)

 

= Person('Bigberg''CN')

p.nationality()

 

# 輸出

Traceback (most recent call last):

  File "G:/python/untitled/study6/靜態方法.py", line 31in <module>

    p.nationality()

  File "G:/python/untitled/study6/靜態方法.py", line 24in nationality

    print('Bigberg is %s.' % self.country)

AttributeError: type object 'Person' has no attribute 'country'

 

# 提示沒有一個 country 屬性  

  2.3、訪問類變數,即 全域性屬性/靜態欄位 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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)

 

= Person('Bigberg''CN')

p.nationality()

 

# 輸出

Bigberg is Chinese.

 

回到頂部

三、屬性方法 

   3.1、定義

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

1

2

3

4

5

6

7

8

9

10

11

12

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)

1

2

= Person('Bigberg''CN')

p.drive()

1

# 輸出 <br>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就可以了

  正常呼叫: 

1

2

3

4

5

6

= Person('Bigberg''CN')

p.drive

 

# 輸出

 

Bigberg is driving a car.

  

  3.2 setter用法

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

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))

 

= Person('Bigberg''CN')

p.drive

 

# 輸出

Bigberg is driving a LAMBORGHINI.

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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

 

= Person('Bigberg''CN')

p.drive = 'Tesla'     # 給屬性賦值

p.drive

 

#輸出

 

set car: Tesla

Bigberg is driving a Tesla.

  3.3 deleter 用法

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

# 以上例

# 我們可以發現普通屬性是可以通過del直接刪除的

# 比如

print(p.name)

del p.name

print(p.name)

 

# 輸出

 

Traceback (most recent call last):

Bigberg

  File "G:/python/untitled/study6/靜態方法.py", line 49in <module>

    print(p.name)

AttributeError: 'Person' object has no attribute 'name'

 

#刪除之後就不能再呼叫了

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

1

2

3

4

5

6

7

del p.drive

 

#輸出

Traceback (most recent call last):

  File "G:/python/untitled/study6/靜態方法.py", line 51in <module>

    del p.drive

AttributeError: can't delete attribute

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

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.

扣了你的車,讓你開豪車...

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

1

2

3

4

5

6

7

8

9

10

11

12

p.drive

 

# 輸出

扣了你的車,讓你開豪車...

Traceback (most recent call last):

  File "G:/python/untitled/study6/靜態方法.py", line 57in <module>

    p.drive

  File "G:/python/untitled/study6/靜態方法.py", line 28in drive

    print('%s is driving a %s.' % (self.name, self.car))

AttributeError: 'Person' object has no attribute 'car'

 

# 提示沒有這個屬性了

回到頂部

 

回到頂部

四、屬性方法應用場景

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

1. 連線航空公司API查詢

2. 對查詢結果進行解析 

3. 返回結果給你的使用者

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

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...")

 

= Flight('CA980')

f.flight_status

f.flight_status = 2

 

#輸出

 

checking flight CA980 status

flight is arrived...

Has changed the flight status to  departured