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允许定义许多定制方法,可以让我们非常方便地生成特定的类。