python面向對象高級編程_類中的默認方法


摘自謬雪峰https://www.liaoxuefeng.com/wiki/1016959663602400/1017501655757856

給一個‘類’綁定屬性和方法

給實例綁定屬性和方法

>>> s = Student()
>>> s.name = 'Michael' # 動態給實例綁定一個屬性

>>> def set_age(self, age): # 定義一個函數作為實例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 給實例綁定一個方法
>>> s.set_age(25) # 調用實例方法
>>> s.age # 測試結果
25

給一個類綁定方法

>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = set_score

通常情況下,上面的set_score方法可以直接定義在class中,但動態綁定允許我們在程序運行的過程中動態給class加上功能,這在靜態語言中很難實現。

限制屬性的綁定__slots__

為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變量,來限制該class實例能添加的屬性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱
>>> s.score = 99 # 綁定屬性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

由於'score'沒有被放到__slots__中,所以不能綁定score屬性,試圖綁定score將得到AttributeError的錯誤。

使用__slots__要注意,__slots__定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的:

class GraduateStudent(Student):
... pass
...

g = GraduateStudent()
g.score = 9999
除非在子類中也定義__slots__,這樣,子類實例允許定義的屬性就是自身的__slots__加上父類的__slots__。

@property用來在類中定義規則,並且外部簡單調用

@property用來在類中定義規則,並且外部簡單調用,即外部實例話后,不用調用方法來設置屬性,而是直接設置屬性

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter      # 沒有score.setter則該屬性為只讀屬性
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

結果:

>>> s = Student()
>>> s.score = 60 # OK,實際轉化為s.set_score(60)
>>> s.score # OK,實際轉化為s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

多重繼承

class Dog(Mammal, Runnable):
pass

類中的默認方法

getattr

只有在沒有找到屬性的情況下,才調用__getattr__,已有的屬性,比如name,不會在__getattr__中查找。

class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99
       else:
            raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)

__call__調用實例本身

class Student(object):
def init(self, name):
self.name = name

def __call__(self):
    print('My name is %s.' % self.name)

調用方式如下:

s = Student('Michael')
s() # self參數不要傳入
My name is Michael.

callable()

通過callable()函數,我們就可以判斷一個對象是否是“可調用”對象。

callable(Student())
True

callable(max)
True

callable([1, 2, 3])
False

callable(None)
False

callable('str')
False

常量的定義——枚舉類Enum

from enum import Enum

Month = Enum('Monster', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
#類似於字典的鍵值對的形式
print(Month.Jan)#返回Monster.Jan

for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)
#結果如下
'''Jan => Monster.Jan , 1
Feb => Monster.Feb , 2
Mar => Monster.Mar , 3
Apr => Monster.Apr , 4
May => Monster.May , 5
Jun => Monster.Jun , 6
Jul => Monster.Jul , 7
Aug => Monster.Aug , 8
Sep => Monster.Sep , 9
Oct => Monster.Oct , 10
Nov => Monster.Nov , 11'''

另一種方法,可見,既可以用成員名稱引用枚舉常量,又可以直接根據value的值獲得枚舉常量。

from enum import Enum, unique

@unique
class Weekday(Enum):
Sun = 0 # Sun的value被設定為0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
@unique裝飾器可以幫助我們檢查保證沒有重復值。

訪問這些枚舉類型可以有若干種方法:

day1 = Weekday.Mon
print(day1)
Weekday.Mon

print(Weekday.Tue)
Weekday.Tue

print(Weekday['Tue'])
Weekday.Tue

print(Weekday.Tue.value)
2

print(day1 == Weekday.Mon)
True

print(day1 == Weekday.Tue)
False

print(Weekday(1))
Weekday.Mon

print(day1 == Weekday(1))
True

Weekday(7)
Traceback (most recent call last):
...
ValueError: 7 is not a valid Weekday

for name, member in Weekday.members.items():
... print(name, '=>', member)
...
Sun => Weekday.Sun
Mon => Weekday.Mon
Tue => Weekday.Tue
Wed => Weekday.Wed
Thu => Weekday.Thu
Fri => Weekday.Fri
Sat => Weekday.Sat


免責聲明!

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



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