两个类的内建函数 一:isinstance()
1 class P1(): 2 3 def __init__(self, name): 4 self.name = name 5 pass 6 7 class P2(P1): 8 A = P1('wang') # 定义类属性!! 9 B = P1('zi')10 11 print(P2.__dict__)12 for i, v in P2.__dict__.items():13 if i =='A':14 print(v)15 print(isinstance(v,P1))
l='<__main__.P1 object at 0x01DF0290>' print(l) print(isinstance(l, P1))
运行结果:
{ '__module__': '__main__', 'A': <__main__.P1 object at 0x01DF0290>, 'B': <__main__.P1 object at 0x01DF0390>, '__doc__': None}<__main__.P1 object at 0x01DF0290>True <__main__.P1 object at 0x01DF0290> False
注意第15行,是v! <__main__.P1 object at 0x01DF0290>这种格式只能被存储,并通过变量传递,不能被赋值。
二:super()
class C(P): def __init__(self): P.__init__(self)###等价于class C(P): def __init__(self): super(C,self).__init__()
super用于查找是根据基类的mor()函数查找上一级的。
具体解释参考:
用来定制类的特殊方法(包括__init__构造器和__del__结构器),它们有些有默认的特定行为,而其他的则没有。
可实现:
重载操作符 + - ...
模拟标准类型 (例子二)
一:__len__内建len()函数
class dog(): def __len__(self): return 100print(len(dog())) # 100
二:__str__ 表示可打印时的输出,__repr__表示运行时的字符串输出,rept()和‘’操纵符号
class RoundFloat2(): def __init__(self,val): assert isinstance(val,float), 'Value must be a float' self.value = round(val,2)
当你
print(RoundFloat2(3.5))
是无法输出正确的数,输出的是<__main__.RoundFloat2 object at 0x01CFB430>
#要定义__str__和__repr__函数def __str__(self): return (str(self.value) ) __repr__ = __str__
如果
class RoundFloat2(float): RoundFloat2是继承自float标准类的,就不需要重新定制,因为float类中已经定义好了__str__和__repr__。
三:迭代器(__iter__和__next__)
3.0中引用时用*.next()的方式会出错,用next(*)函数或者*.__next__()的方式
a=range(10)i=iter(a)# for j in range(10):# print(i.__next__()) #这样也行for j in range(10): print(next(i))
可以自己定义一个迭代器,__iter__仅返回self,对象就被声明为迭代器。
class AnyIter(): #建立迭代器(类) def __init__(self, data, safe=False): self.safe = safe self.iter = iter(data) # iter()函数会检查你传递的是不是一个序列,如果是,用__next__函数根据索引从0迭代到序列结束 def __iter__(self): return self def __next__(self, howmany=2): #内建__next__函数 retval = [] for eachItem in range(howmany): retval.append(self.iter.__next__()) #或者用next(*)迭代 return retvalfor item in AnyIter(range(10)): #AnyIter(range(10))是一个迭代器,for循环语句中每一次执行一次,就会执行__next__()函数直到遍历结束。 print(item)a= AnyIter(range(10))for j in range(1,5): print(j,':',a.__next__(j)) #主动调用__next__函数,运行结果
结果为:
[0, 1][2, 3][4, 5][6, 7][8, 9]1 : [0]2 : [1, 2]3 : [3, 4, 5]4 : [6, 7, 8, 9]
四: 包装 (__getattr__)
授权
1 class Wrap(): 2 def __init__(self,obj): 3 self.__data = obj 4 def get(self): 5 return self.__data 6 def __str__(self): 7 return '%r' % self.__data 8 def __getattr__(self, attr): 9 return getattr(self.__data,attr)10 11 a = Wrap(3+5j)12 print(a)13 print(a.conjugate())14 print(getattr(a,'conjugate'))15 16 b=Wrap((1,2,3))17 print(b.index(2))18 #print(b[2]) 会报错
用__getattr__实现继承以后,只有当调用的属性或者方法不能搜索到才调用。
因为复数中存在conjuate属性,所以13行可以调用。
第14行试图去调用conjugate属性,没有找到,所以会去__getattr__中找,所以输出结果为:<built-in method conjugate of complex object at 0x002656E0>。
(getattar 和 __getattar__ 没有大联系,只是getattr找不到属性时,会调用__getattr__进行查找)
第18行的切片操纵不存在列表的方法列表中,不是通过__getitem__()特殊方法实现的,所以它不是属性,不能被访问。执行第18行会试图去调用__getitem__函数,但是__getitem__函数没有作为列表实例的方法进行定义。
上面的结果为:
(3+5j)(3-5j)1
授权是包装的一个特性,包装是对一个已经存在的对象增加新的、删除不要的或修改已存在的功能。
下面例子,描述了一个包装文件对象的类。
它的用法完全和open()文件对象一样,只是对write函数进行了自定义,其他所有属性都已授权给文件对象。
1 class CapOpen(): 2 def __init__(self,fn,mode='r'): 3 self.file = open(fn,mode) 4 5 def write(self,line): 6 self.file.write(line.upper()) 7 8 def __getattr__(self, item): 9 return getattr(self.file,item)10 11 def __iter__(self):12 return self.file
可以进行下面的操纵。
1 f=CapOpen('sdf','w')2 f.write('delegation example\n')3 f.write('fayw is godd\n')4 f.close()5 f=CapOpen('sdf','r')6 for eachline in f:7 print (eachline)
结果为:
DELEGATION EXAMPLEFAYW IS GODD