zoukankan      html  css  js  c++  java
  • 类的专有方法

    #前面已经了解了类的访问权限、私有变量和私有方法,除了自定义私有变量和方法外,Python类还可以定义专有方法。专有方法是在特殊情况下或使用特殊语法时由Python调用的,而不是像普通方法一样在代码中直接调用。
    #看到形如__xxx__的变量或函数名就要注意,这在Python中是有特殊用途的。
    #__init__我们知道怎么用了,Python的class中有许多这种有特殊用途的函数,可以帮助沃恩定制类。下面介绍这种特殊类型的函数定制类的方法。
     
    1、__str__
    #介绍之前,我们先定义一个Student类,定义如下:
    1 #!/usr/bin/python3
    2 #-*-coding:UTF-8-*-
    3 #类的专有方法
    4 
    5 class Student(object):
    6     def __init__(self,name):
    7         self.name=name
    8 
    9 print(Student('xiaoming'))
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171212>python __str__.py
    2 <__main__.Student object at 0x0274A450>
    #执行结果输出一堆字符串,一般人看不懂,没什么可用性,也不好看。怎样才能输出的好看呢?
    #只需要我们定义好__str__()方法,返回一个好看的字符串就可以了。重新定义上面的实例:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #类的专有方法
     4 
     5 class Student(object):
     6     def __init__(self,name):
     7         self.name=name
     8 
     9     def __str__(self):
    10         return '学生名称:%s'%self.name 
    11 
    12 print(Student('xiaoming'))
    #执行结果为:
    1 D:Pythonworkspacedatatime20171212>python __str__.py
    2 学生名称:xiaoming
    #由执行结果看到,这样输出的实例不但好看,而且是我们想要的。
    #如果在交互模式下输入如下:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #类的专有方法
     4 
     5 class Student(object):
     6     def __init__(self,name):
     7         self.name=name
     8 
     9 
    10 
    11 #print(Student('xiaoming'))
    12 s=Student('xiaoming')
    13 print(s)
    #执行结果为:
    1 D:Pythonworkspacedatatime20171212>python __str__.py
    2 <__main__.Student object at 0x0331A450>
    #由执行结果看到,输出的实例还跟之前一样,不容易识别。
    #这是因为直接显示变量调用的不是__str__(),而是__repr__,两者的区别在于__str__()返回用户看到的字符串,而__repr__()返回的程序开发者看到的字符串。也就是说,__repr__()是为调试服务的。
    #解决的办法是在定义个__repr__。通常,__str__()和__repr__()代码是一样的,所以有一个偷懒的写法:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #类的专有方法
     4 
     5 class Student(object):
     6     def __init__(self,name):
     7         self.name=name
     8 
     9     def __str__(self):
    10         return '学生名称:%s'%self.name 
    11 
    12     __repr__=__str__
    13 
    14 #print(Student('xiaoming'))
    15 s=Student('xiaoming')
    16 print(s)
    #执行结果为:
    1 D:Pythonworkspacedatatime20171212>python __str__.py
    2 学生名称:xiaoming
    #可以看到,已经得到满意的结果了。
     
    2、__iter__
    #如果想要将一个类用于for..in循环,类似list或tuple一样,就必须实现一个__iter__()方法。该方法返回一个迭代对象,Python的for循环会不断调用该迭代对象的__next__()方法,获得循环的下一个值,知道遇到StopIteration错误时退出循环。
    #我们以斐波那契数列为例,写一个可以作用于for循环的Fib类:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #__iter__
     4 
     5 class Fib(object):
     6     def __init__(self):
     7         self.a,self.b=0,1 #初始化两个计数器a、b
     8 
     9     def __iter__(self):
    10         return self #实例本身就是迭代对象,返回自己
    11 
    12     def __next__(seflf):
    13         self.a,self.b=self.b,self.a+self.b #计算下一个值
    14         if self.a>100000:  #退出循环的条件
    15             raise StopIteration();
    16         return self.a #返回下一个值
    17         #下面我们把Fib实例作用于for循环。
    18 for n in Fib():
    19        print(n)
    #执行结果如下:
     1 D:Pythonworkspacedatatime20171213>python __iter__.py
     2 1
     3 1
     4 2
     5 3
     6 5
     7 8
     8 13
     9 21
    10 34
    11 55
    12 89
    13 144
    14 233
    15 377
    16 610
    17 987
    18 1597
    19 2584
    20 4181
    21 6765
    22 10946
    23 17711
    24 28657
    25 46368
    26 75025
    3、__getitem__
    #Fib实例虽然能够作用于for循环,和list有点像,但是不能将它当成list使用。比如取第3个元素:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #__iter__
     4 
     5 class Fib(object):
     6     def __init__(self):
     7         self.a,self.b=0,1 #初始化两个计数器a,b
     8 
     9     def __iter__(self):
    10         return self #实例化本身就是迭代对象,因此返回自己
    11 
    12     def __next__(self):
    13         self.a,self.b=self.b,self.a+self.b #计算下一个值
    14         if self.a>100000: #退出循环的条件
    15             raise StopIteration();
    16         return self.a #返回下一个值
    17 for n in Fib()[3]:
    18     print(n)
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __iter__.py
    2 Traceback (most recent call last):
    3   File "__iter__.py", line 17, in <module>
    4     for n in Fib()[3]:
    5 TypeError: 'Fib' object does not support indexing
    #由执行结果看到,取元素时报错了。该怎么办?
    #要像list一样按照下标取元素,需要实现__getitem__()方法,代码如下:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #__getitem__
     4 
     5 class Fib(object):
     6     def __getitem__(self,n):
     7         a,b=1,1
     8         for x in range(n):
     9             a,b=b,a+b
    10         return a
    #下面尝试取得数列的值:
    1 fib=Fib()
    2 print(fib[3])
    3 print(fib[8])
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __getitem__.py
    2 3
    3 34
    #由执行结果看到,可以成功获取对应数列的值了。
     
    4、__getattr__
    #正常情况下,调用类的方法或属性时,如果类的方法或属性不存在就会报错。比如定义Student类:
    1 #!/usr/bin/python3
    2 #-*-coding:UTF-8-*-
    3 #__getattr__
    4 
    5 class Student(object):
    6     def __init__(self,name):
    7         self.name='xiaoming'
    #对于上面的代码,调用name属性不会有任何问题,但是调用不存在的score属性就会报错。执行以下代码:
    1 stu=Student('xiaoming')
    2 print(stu.name)
    3 print(stu.score)
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __getattr__.py
    2 xiaoming
    3 Traceback (most recent call last):
    4   File "__getattr__.py", line 11, in <module>
    5     print(stu.score)
    6 AttributeError: 'Student' object has no attribute 'score'
    #由输出结果看到,错误信息告诉我们没有找到score属性。对于这种情况,该怎么解决呢?
    #要避免这个错误,除了可以添加一个score属性外,Python还提供了另一种机制,就是写一个__getattr__()方法,动态返回一个属性。上面的代码修改如下:
     1 #!/usr/bin/python3
     2 #-*-coding:UTF-8-*-
     3 #__getattr__
     4 
     5 class Student(object):
     6     def __init__(self,name):
     7         self.name='xiaoming'
     8 
     9     def __getattr__(self,attr):
    10         if attr=='score':
    11             return 96
    12 
    13 stu=Student('xiaoming')
    14 print(stu.name)
    15 print(stu.score)
    #当调用不存在的属性时(如score),Python解释器就会调用__getattr__(self,'score')尝试获取属性,这样就有机会返回score的值。执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __getattr__.py
    2 xiaoming
    3 96
    #由输出结果看到,可以正确输出不存在的属性的值了。
    #注意,只有在没有找到属性的情况下才调用__getattr__,已有的属性(如name),不会在__getattr__中查找。此外,如果所有调用都会返回None(如stu.abc),就是定义的__getattr__,哦人返回None。
     
    5、__call__
    #一个对象实例可以有自己的属性和方法,调用实例的方法时使用instance.method()调用。能不能直接在实例本身调用,答案是可以的。
    #任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用,例如:
    1 #!/usr/bin/python3
    2 #-*-coding:UTF-8-*-
    3 #__call__
    4 
    5 class Student(object):
    6     def __init__(self,name):
    7         self.name=name
    8     def __call__(self):
    9         print('名称:%s'%self.name)
    #执行如下操作:
    1 stu=Student('xiaoming')
    2 stu()
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __call__.py
    2 名称:xiaoming
    #由输出结果看到,可以直接对实例进行调用并得到结果。
    #__call__()还可以定义参数。对实例进行直接调用就像对一个函数调用一样,完全可以把对象看成函数,把函数看成对象,因为这两者本来就是有根本的区别。
    #如果把对象看成函数,函数本身就可以在运行期间动态创建出来,因为类的实例都是运行期间创建出来的。
    #怎判断一个变量是对象还是函数呢?
    #很多时候判断一个对象能否被调用,可以使用Callable()函数,比如函数和上面定义带有__call__()的类实例。输入如下:
    1 print(callable(Student('xiaoqiang')))
    2 print(callable(max))
    3 print(callable([1,2,3]))
    4 print(callable(None))
    5 print(callable('a'))
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171213>python __call__.py
    2 True
    3 True
    4 False
    5 False
    6 False
    #由输出结果看到,通过callable()函数可以判断一个对象是否为’可调用‘对象。
  • 相关阅读:
    进程DLL注入
    静态链接库LIB
    利用MoveFileEx实现程序的隐藏、自启动与自删除
    QueueUserApc实现DLL注入的测试
    简单说说SSDT
    ural 1521. War Games 2 约瑟夫环 SBT实现
    次小生成树 (附:poj1679)
    hoj 1138 LC Display
    hoj 3029 Dictionary 模拟队列
    hoj 2578 Super_Stack 模拟栈
  • 原文地址:https://www.cnblogs.com/DLHe/p/8065449.html
Copyright © 2011-2022 走看看