Python面向对象高级编程-__slots__定制类,枚举

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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__()两种方法,__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__定制类,枚举的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象高级编程(__slots__多继承定制类)-6

Python学习---面向对象高级编程

Python面向对象进阶之高级编程

Python学习之七面向对象高级编程——__slots__的使用

Python 面向对象之高级编程

Python面向对象高级编程