python物件導向高階程式設計 類中的預設方法

2022-01-19 11:28:07 字數 4799 閱讀 4216

摘自謬雪峰

>>> 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加上功能,這在靜態語言中很難實現。

為了達到限制的目的,python允許在定義class的時候,定義乙個特殊的__slots__變數,來限制該class例項能新增的屬性:

class student(object):

__slots__ = ('name', 'age') # 用tuple定義允許繫結的屬性名稱

>>> s.score = 99 # 繫結屬性'score'

traceback (most recent call last):

file "", line 1, in 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用來在類中定義規則,並且外部簡單呼叫,即外部例項話後,不用呼叫方法來設定屬性,而是直接設定屬性

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__,已有的屬性,比如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)

class student(object):

definit(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(student())

true

callable(max)

true

callable([1, 2, 3])

false

callable(none)

false

callable('str')

false

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)

2print(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

python 物件導向高階程式設計

python 裝飾器 property使用 classscreen property defwidth self returnself.width pass width.setter defwidth self,value self.width value property defheight se...

python物件導向高階程式設計

1.繫結方法 給所有例項都繫結方法,可以給class繫結方法 def set score self,score self.score score student.set score set score 給class繫結方法後,所有例項均可呼叫。但是,如果我們想要限制例項的屬性怎麼辦?比如,只允許對s...

物件導向高階程式設計

相同class的各物件互為友元 class complex int func const complex param private double re,im string inline string string const char cstr 0 else inline string strin...