Python 定制类

1
__str__() 和 __repr__()

修改打印一个实例时的默认值。

修改前:

>>> class Student(object):
...     def __init__(self,name):
...         self.name = name
... 
>>> s=Student('syztoo')
>>> print(s)
<__main__.Student object at 0x7fde19208128>
>>> s
<__main__.Student object at 0x7fde192082b0>

定制 __str__() 方法:

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

定制 __repr__() 方法:

>>> class Student(object):
...     def __init__(self,name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name: %s)' % self.name
...     __repr__ = __str__
... 
>>> s=Student('syztoo')
>>> print(s)
Student object (name: syztoo)
>>> s
Student object (name: syztoo)

2

__iter__()

如果一个类想被用于 for ... in 循环,类似 list 或 tuple 那样,就必须实现一个 __iter__() 方法,该方法返回一个迭代对象,然后,Python 的 for 循环就会不断调用该迭代对象的 __next__() 方法拿到循环的下一个值,直到遇到 StopIteration 错误时退出循环。

>>> class Fib():
...      def __init__(self):
...          self.a,self.b = 0,1
...      def __iter__(self):
...          return self
...      def __next__(self):
...          self.a,self.b = self.b,self.a+self.b
...          if self.a > 1000:
...              raise StopIteration()
...          return self.a
... 
>>> for n in Fib():
...      print(n)
... 
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987

3

__getitem__(self,key)

使用 __iter__() 方法定制类后,虽然类可以作用于 for 循环,但并不能像列表那样通过索引取出元素,比如:

>>> Fib()[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Fib' object does not support indexing

提示类对象不支持索引。

可以使用 __getitem__(self,key) 方法为类定制索引,该方法需要一个固定参数key(及索引,从0开始),该方法返回key对应的值。

>>> class Fib(object):
...     def __getitem__(self,key):
...         a,b = 1,1
...         for i in range(key):
...             a,b = b,a+b
...         return a
... 
>>> f = Fib()
>>> f[0]
1
>>> f[100]
573147844013817084101

定制切片和步长功能:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

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
            step = n.step
            if start is None:
                start = 0
            a, b = 1, 1
            L = []
            for x in range(stop):
                if step:
                    if x >= start and (x - start) % step == 0:
                        L.append(a)
                else:
                    if x >= start:
                        L.append(a)
                a, b = b, a + b
            return L

f = Fib()
print(f[100])
print(f[10:20])
print(f[:10])
print(f[10:20:2])

4

__getattr__()

class Student(object):

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

    def __getattr__(self, attr):
        if attr=='score':
            return 99

当我们调用类不存在的属性时,Python解释器会尝试从 __getattr__() 方法中获取该属性,如果 __getattr__() 方法中,有定义该属性,那么我们有机会返回该属性的值:

>>> s = Student()
>>> s.name
'Michael'
>>> s.score
99
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'

5

__call__()

任何类,只需要定义一个__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__()还可以定义参数:

class Chain(object):
    def __init__(self, path=''):
       self.__path = path

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

   def __call__(self, path):
       return Chain('%s/%s' % (self.__path, path))

   def __str__(self):
       return self.__path

   __repr__ = __str__
>>> print(Chain().users('michael').repos)
/users/michael/repos

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值