3.22(下)

174 阅读3分钟

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()还可以定义参数。对实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象,因为这两者之间本来就没啥根本的区别。 如果你把对象看成函数,那么函数本身其实也可以在运行期动态创建出来,因为类的实例都是运行期创建出来的,这么一来,我们就模糊了对象和函数的界限。