Python面向對象高級編程-__slots__、定制類,枚舉
當在類體內定義好各種屬性後,外部是可以隨便添加屬性的,Python中類如何限制實例的屬性?
Python自帶了很多定制類,諸如__slots__,__str__
__slots__
__slots__方法是在類創建時,為實例限定屬性的
class Student(object):
__slots__=(‘name‘,‘age‘)
pass
>>>s = Student()
>>>s.name=‘tom‘
>>>s.age=‘age‘
>>>s.score=10 #AttributeError: ‘ Student‘ object has no attribute ‘score‘
當__slots__已經進行限定時,再去給實例綁定沒有限定的屬性,就會報錯。
__slots__作用域僅限當前的類,當父類中有__slots__屬性時,子類中並沒有限制,當子類中定義__slots__時,子類的實例限制就是子類本身加上父類的__slots__。
__str__和__repr__
如果要把一個類的實例變成 str,就需要實現特殊方法__str__():
class Person(object): def __init__(self, name, gender): self.name= name self.gender = gender def __str__(self): return ‘(Person: %s, %s)‘ % (self.name, self.gender)
>>>p = Person(‘tom‘,‘male‘)
>>>print(p)
(Person:tom,male)
>>>p #直接打印p __str__不會被調用
<main.Person object at 0x10c941890>
因為 Python 定義了__str__()和__repr__()
有一個偷懶的定義__repr__的方法:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return ‘(Person: %s, %s)‘ % (self.name, self.gender)
__repr__ = __str__
__len__
如果一個類表現得像一個list,要獲取有多少個元素,就得用 len() 函數。
要讓 len() 函數工作正常,類必須提供一個特殊方法__len__(),它返回元素的個數。
例如,我們寫一個 Students 類,把名字傳進去:
class Students(object): def __init__(self, *args): self.names = args def __len__(self): return len(self.names)
>>>s = Student(‘a‘,‘b‘,‘c‘) #只要正確實現了__len__()方法,就可以用len()函數返回Students實例的“長度”
>>>print len(s)
3
__call__
Python所有的函數都是可調用對象。
一個類實例也可以變成一個可調用對象,只需要實現一個特殊方法__call__()。
我們把 Person 類變成一個可調用對象:
class Person(object): def __init__(self, name, sex): self.name = name self.sex = sex def __call__(self, friend): print(‘My name is %s...‘ % self.name) print(‘My friend is %s...‘ % friend)
>>>p = Person(‘tom‘,‘boy‘)
>>>p(‘jerry‘) #對實例直接調用
My name is tom
My friend is jerry
枚舉
定義枚舉引入模塊enum,枚舉類繼承的時Enum類
from enum import Enum
class Book(Enum):
a = 1
math = 2
english = 3
linux = 4
c++ = 5
訪問枚舉有很多方法
>>>Book.a
<Book.a: 1>
>>>Book(1)
<Book.a: 1>
>>>print(Book.a)
Book.a
>>>print(Book(1))
Book.a
>>>Book.a.name
‘a‘
>>>Book.a.value
1
如果枚舉中成員名有重復的話,就會報錯TypeError: Attempted to reuse key: ‘a‘
成員的值時允許重復的,但是訪問時還是第一個成員屬性,Python將重復的第二個成員看做第一個的別名
from enum import Enum
class Book(Enum):
a = 1
b = 1
>>>Book.a
<Book.a: 1>
>>>Book.b #訪問b也變成了打印a屬性,b被視為a的別名
<Book.a :1>
如果限制枚舉沒有重復的話,引入unique模塊,unique是一個類裝飾器,用來約束值
from enum import Enum,unique
@unique
class Book(Enum):
a = 1
b = 1
>>>print(Book.a.value)
ValueError:dupplicate values found in <enum ‘Book‘>:b -> a
枚舉支持叠代器
>>>for b in Book:
print(b)
Book.a、...
成員值重復時,只能拿到第一個成員,若要不管重復,列出所有的,使用__members__方法
from enum import Enum
class Book(Enum):
a = 1
math = 2
english = 3
linux = 4
c++ = 5
for b in Book.__members__.items():
print(b)
#以元組形式打印
(‘a‘,<Book.a: 1>)、(‘math‘,<Book.math: 2>)、、、
Python面向對象高級編程-__slots__、定制類,枚舉