类的内建函数和用来定制类的特殊方法

两个类的内建函数
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()函数查找上一级的。

具体解释参考:

http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html

 

用来定制类的特殊方法(包括__init__构造器和__del__结构器),它们有些有默认的特定行为,而其他的则没有。

可实现:

重载操作符     + -   ...

模拟标准类型   (例子二)

一:__len__内建len()函数
class dog():
    def __len__(self):
        return 100

print(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 retval
for 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)
<built-in method conjugate of complex object at 0x002656E0>
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 EXAMPLE

FAYW IS GODD

 

 

posted on 2017-01-15 00:53  wzxds02  阅读(301)  评论(0编辑  收藏  举报

导航