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
这个!!!不能当List用,没法取下标!!!!!!!!!!!!!嗷!!! getitem()用这个!!!!!!!!!!!!!
要表现得像list那样按照下标取出元素,需要实现__getitem__()方法: class Fib(object): def getitem(self, n): a, b = 1, 1 for x in range(n): #遍历 循环 惰性 Fib(5),给命令具体数字 再运行计算 a, b = b, a + b #加上 return a
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:stop:step 参数吧 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 f=Fib() print(f[0:5]) #加上step也一样啦啊!!!!!!!!! 此外,如果把对象看成dict,getitem()的参数也可能是一个可以作key的object,例如str。 与之对应的是__setitem__()方法,把对象视作list或dict来对集合赋值。最后,还有一个__delitem__()方法,用于删除某个元素。 总之,通过上面的方法,我们自己定义的类表现得和Python自带的list、tuple、dict没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。
API 预先定义的函数 URL 统一资源定位符 //网址 SDK 软件开发工具包
【【getattr】】
class A(object): ... bar = 1 ...
a = A() getattr(a, 'bar') # 获取属性 bar 值 1
getattr(a, 'bar2') # 属性 bar2 不存在,触发异常 Traceback (most recent call last): File "", line 1, in AttributeError: 'A' object has no attribute 'bar2'
getattr(a, 'bar2', 3) # 属性 bar2 不存在,但设置了默认值 3
class Student(object):
def __init__(self):
self.name = 'Michael'
def __getattr__(self, attr):
if attr=='score': #属性不存在
return 66
s = Student() b=s.score print(b)
如果要写SDK,给每个URL对应的API都写一个方法,那得累死,而且,API一旦改动,SDK也要改。 利用完全动态的__getattr__,我们可以写出一个链式调用: class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
return Chain('%s/%s' % (self._path, path)) #哪里链了啊啊啊啊啊啊 你瞎啊啊啊啊Chain看不见吗这不就链了吗!!!!!!!!!
def __str__(self):
return self._path
__repr__ = __str__
试试:
Chain().status.user.timeline.list '/status/user/timeline/list' 这样,无论API怎么变,SDK都可以根据URL实现完全动态的调用,而且,不随API的增加而改变!
call()还可以定义参数。对实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象,因为这两者之间本来就没啥根本的区别。 如果你把对象看成函数,那么函数本身其实也可以在运行期动态创建出来,因为类的实例都是运行期创建出来的,这么一来,我们就模糊了对象和函数的界限。