zoukankan      html  css  js  c++  java
  • 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(object)这个功能。意思是当需要显示一个对象在屏幕上时,将这个对象的属性或者是方法整理成一个可以打印输出的格式。

    这个功能与eval也可以对应。打印出的结果直接放到eval里,通常可以获得原来的对象。

    >>> from datetime import datetime
    >>> t1 = datetime.now()
    >>> t1
    datetime.datetime(2017, 12, 8, 16, 50, 47, 766613)
    >>> print(t1)
    2017-12-08 16:50:47.766613
    >>> print(repr(t1))
    datetime.datetime(2017, 12, 8, 16, 50, 47, 766613)
    >>> print(str(t1))
    2017-12-08 16:50:47.766613

    与此相类似的功能是__str__

    比如你有一个People类,当打印时你只希望它打印出人名,那么你可以在__str__函数里写上return self.name , 这样当需要People当作一个字符串时,返回的就是人名。

    有一个偷懒的定义__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>)、、、
  • 相关阅读:
    Func<T>、Action<T> 的区别于说明
    Invoke()/BeginInvoke()区别
    C# Linq处理list数据
    C# 的三种序列化方法
    P3368 【模板】树状数组 2
    P2058 海港
    2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
    2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解
    2019.6.18 校内测试 分析+题解
    P1310 表达式的值
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7658486.html
Copyright © 2011-2022 走看看