1. 程式人生 > >Python面向對象高級編程-__slots__、定制類,枚舉

Python面向對象高級編程-__slots__、定制類,枚舉

成了 模塊 person 兩種方法 繼承 math end spa ...

當在類體內定義好各種屬性後,外部是可以隨便添加屬性的,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__()

兩種方法,__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__、定制類,枚舉