8 python 定制自己的类,实现查看属性,按index取值,迭代,切片等个性化类

1 str
class Student(object):
    def __init__(self,name):
        self.name = name
print Student('Michael')
<__main__.Student object at 0x7fa939eda310>

怎么打印的好看呢?

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

上面说明print 调用的是str这个方法,对不对?
但是不用print 输出还是很难看,例如:

Student('huxiang')
<__main__.Student at 0x7fa939eda250>

这是为什么呢?直接输出调用的是另一个方法了,改写如下

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

说明直接输出也是调用一个方法,而这个方法是repr

2 iter 实现迭代
class Fib(object):
    def __init__(self):
        self.a,self.b = 0,1 #初始值
    def __iter__(self):
        return self
for n in Fib():
    print n
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-8-b601c92d0330> in <module>()
----> 1 for n in Fib():
      2     print n


TypeError: iter() returned non-iterator of type 'Fib'
class Fib(object):
    def __init__(self):
        self.a,self.b = 0,1 #初始值
    def __iter__(self):
        return self
    def next(self):#next是什么?也是迭代时要用到的吗?
        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
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657
46368
75025
3 getitem用于取得第几个元素,所以改写这个方法就可以直接取某个元素了

例如这里没定义,直接去会报错

Fib()[5]
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-11-f91ed6abd284> in <module>()
----> 1 Fib()[5]


TypeError: 'Fib' object does not support indexing
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[5]
8

但是还不能切片,怎么实现切片呢?还是修改getitem这个方法,判断传入值的类型,然后再决定返回的类型

class Fib(object):
    def __getitem__(self,n):
        if isinstance(n,int):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n,slice):
            start = n.start
            stop = n.stop
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L
  File "<ipython-input-15-e90f9954e169>", line 6
    a, b = b, a + b
               ^
SyntaxError: invalid syntax

我靠我错在哪?

class Fib(object):
    def __getitem__(self, n):
        if isinstance(n, int):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice):
            start = n.start
            stop = n.stop
            a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L

下面就可以用切片了,爽!

f = Fib()
f[0:5]
[1, 1, 2, 3, 5]

总之,通过上面的方法,我们自己定义的类表现得和Python自带的list、tuple、dict没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。

另外还有其他的 一些’内在方法’,例如:
Python解释器会试图调用getattr(self, ‘score’)来尝试获得属性,这样,我们就有机会返回score的值:

class Student(object):

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

    def __getattr__(self, attr):
        if attr=='score':
            return 99
s = Student()
print s.name
print s.score
Michael
99

只需要定义一个call()方法,就可以直接对实例进行调用。请看示例:

class Student(object):
    def __init__(self):
        self.name = 'huxiang'
    def __call__(self):
        print('My name is %s.' % self.name)
s = Student()
s()
My name is huxiang.

小结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值