OOP-定制类

1.__len__()

2.__str__()  美化实例调用

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
>>> print(Student('Michael'))
<__main__.Student object at 0x109afb190>
---------------------------------------
>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name: %s)' % self.name
...
>>> print(Student('Michael'))
Student object (name: Michael)

3.__repr__()  美化直接打印出的实例变量

>>> s = Student('Michael')
>>> s
<__main__.Student object at 0x109afb310>
---------------------------------------------
class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return 'Student object (name=%s)' % self.name
    __repr__ = __str__

4.__iter__()+__next__()  迭代器协议将类变为可迭代对象(用于for-in)

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration()
        return self.a # 返回下一个值

---------------------------------
>>> for n in Fib():
...     print(n)
...
1
1
2
3
5
...
46368
75025

5.__getitem__()  使对象实现迭代功能

类实例按下标存取(像list)

class Fib(object):
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a

#现在,就可以按下标访问数列的任意一项了:

>>> f = Fib()
>>> f[0]
1
>>> f[1]
1
>>> f[2]
2
>>> f[3]
3
>>> f[10]
89
>>> f[100]
573147844013817084101

切片:__getitem__()传入的参数可能是一个int,也可能是一个切片对象slice,所以要做判断

class Fib(object):
    def __getitem__(self, n):
        if isinstance(n, int): # n是索引
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice): # n是切片
            start = n.start
            stop = n.stop
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L

#现在试试Fib的切片:

>>> f = Fib()
>>> f[0:5]
[1, 1, 2, 3, 5]
>>> f[:10]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

  与之对应的是__setitem__()方法,把对象视作list或dict来对集合赋值。最后,还有一个__delitem__()方法,用于删除某个元素。

  总之,自定义类和Python自带的list、tuple、dict没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。

6.__getattr__  动态返回属性

  类中找属性--有,返回

        没有,到__getattr__找--有,返回

                   没有,报错处理AttributeError

class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99
-------------------------------
>>> s = Student()
>>> s.name
'Michael'
>>> s.score
99
#返回函数也是完全可以的:
class Student(object):

    def __getattr__(self, attr):
        if attr=='age':
            return lambda: 25
#只是调用方式要变为:
>>> s.age()
25
#属性限制
class Student(object):

    def __getattr__(self, attr):
        if attr=='age':
            return lambda: 25
        raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)

链式调用实例:

class Chain(object):

    def __init__(self, path=''):
        self._path = path

    def __getattr__(self, path):
        return Chain('%s/%s' % (self._path, path))

    def __str__(self):
        return self._path

    __repr__ = __str__
-------------------------------

>>> Chain().status.user.timeline.list
'/status/user/timeline/list'

7.__call__  直接对实例调用

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)

------------------------
>>> s = Student('Michael')
>>> s() # self参数不要传入
My name is Michael.

__call__还可定义参数(将对象看成函数)

判断对象是否可调用callable()

>>> callable(Student())
True
>>> callable(max)
True
>>> callable([1, 2, 3])
False
>>> callable(None)
False
>>> callable('str')
False

Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类。

本节介绍的是最常用的几个定制方法,还有很多可定制的方法,请参考Python的官方文档

猜你喜欢

转载自www.cnblogs.com/jpga/p/12586129.html