Python——类的专有方法

Python除了自定义私有变量和方法外,还可以定义专有方法。专有方法是在特殊情况下或使用特殊语法时由python调用的,而不是像普通方法一样在代码中直接调用。看到形如__XXX__的变量或函数名时就需要注意下,这在python中是有特殊用途的 

  • __init__ : 构造函数,在生成对象时调用
  • __del__ : 析构函数,释放对象时使用
  • __repr__ : 打印,转换
  • __setitem__ : 按照索引赋值
  • __getitem__: 按照索引获取值
  • __len__: 获得长度
  • __cmp__: 比较运算
  • __call__: 函数调用
  • __add__: 加运算
  • __sub__: 减运算
  • __mul__: 乘运算
  • __div__: 除运算
  • __mod__: 求余运算
  • __pow__: 乘方

 

1. __str__

定义一个 Student 类:

class Student(object):
    def __init__(self, name):
        self.name = name

print(Student('zth'))

执行结果:

<__main__.Student object at 0x03DFDDB0>

1、由上面代码可以看出如果直接输出一个类的实例的话,得到的是一个特殊的字符串(程序开发者所用的)
2、如果要把一个类的实例变成str,就需要实现特殊方法__str__( )方法

3、__str__方法必须要return一个字符串类型的返回值,作为对实例对象的字符串描述

class Student(object):
    def __init__(self, name):
        self.name = name
        
    def __str__(self):
        return "学生的姓名:%s"%self.name

print(Student('zth'))

执行结果:

学生的姓名:zth

交互模式下:

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
...     def __str__(self):
...         return "学生的姓名:%s"%self.name
...
>>>
>>> print(Student('zth'))
学生的姓名:zth
>>>
>>> s = Student('zth')
>>>
>>> s
<__main__.Student object at 0x02B10C30>
>>>
>>> print(s)
学生的姓名:zth

原因是直接显示变量调用的不是  __str__() ,而是 __repr__(),两者的区别在于__str__() 返回用户看到的字符串,而 __repr__() 返回程序开发者看到的字符串。也就是__repr__() 是为调试服务的。

解决办法是再定义一个__repr__。通常__str__() 和 __repr__() 代码是一样的,可以如下简写:

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
...     def __str__(self):
...         return "学生的姓名:%s"%self.name
...
...     __repr__ = __str__
...
>>>
>>> s = Student('zth')
>>>
>>> s
学生的姓名:zth

2. __iter__

如果想要将一个类用于 for ... in 循环,类似 list 或 tuple 一样,就必须实现一个__iter__()  方法。该方法返回一个迭代对象,Python 的 for  循环会不断调用该迭代对象的  __next__()  方法,获得循环的下一个值,直到遇到 StopIteration 错误时退出循环。

如下:一个作用于 for 循环的斐波那契数列类:

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 > 100:                 # 退出循环的条件
            raise StopIteration();
        return self.a                   # 返回下一值

for n  in Fib():
    print(n)

执行结果:

1
1
2
3
5
8
13
21
34
55
89

3. __getitem__

Fib 实例虽然能够作用于 for 循环,和 list 有点像,但是不能将它当成 list 使用。比如取第3个元素:

>>> Fib()[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Fib' object does not support indexing

若要像list一样按照索引来获取元素,需要实现__getitem__()方法

>>> class Fib(object):
...     def __getitem__(self,n):
...         a = 0
...         b = 1
...         for x in range(n):
...             a,b = b , a+b
...         return a
...
>>>
>>> fib = Fib()
>>>
>>> fib[3]
2
>>>
>>> fib[5]
5

4. __getattr__

正常情况下,调用类的方法或属性时,如果类的方法或属性不存在就会报错。

定义Student类:

>>> class Student(object):
...     def __init__(self):
...             self.name = 'zth'
...
>>>
>>> s = Student()
>>>
>>> s.name
'zth'
>>>
>>> s.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'

要避免这个错误,除了可以添加一个score属性外,Python还提供了另一种机制,就是写一个__getattr__()方法,动态返回一个属性。

>>> class Student:
...     def __init__(self):
...             self.name = 'zth'
...     def __getattr__(self,attr):
...             if attr == 'age':
...                     return 20
...
>>>
>>> s = Student()
>>>
>>> s.name
'zth'
>>> s.age
20

注意,只有在没有找到属性的情况下才调用__getattr__,已有的属性(如name),不会在__getattr__中查找。此外,如果所有调用都会返回None(如stu.abc),就是定义的__getattr__,返回None。

5. __call__

一个对象实例可以有自己的属性和方法,调用实例的方法时使用  instance.method()  调用。能不能直接在实例本身调用,答案是可以的。

任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用

>>> class Student:
...     def __init__(self,name):
...             self.name = name
...     def __call__(self):
...             print('姓名:%s'%self.name)
...
>>>
>>> s = Student('zth')
>>>
>>> s()
姓名:zth

__call__() 还可以定义参数。对实例进行直接调用就像对一个函数调用一样,完全可以把对象看成函数,把函数看成对象,因为这两者本来就是有根本的区别。

如果把对象看成函数,函数本身就可以在运行期间动态创建出来,因为类的实例都是运行期间创建出来的。 
怎判断一个变量是对象还是函数呢? 
很多时候判断一个对象能否被调用,可以使用Callable()函数,比如函数和上面定义带有__call__()的类实例。

>>> callable(Student('zth'))
True
>>>
>>> callable(max)
True
>>>
>>> callable([1,3,5])
False
>>>
>>> callable(None)
False

6.  getattr():

getattr( ) 函数用于返回一个对象指定的属性值。如果指定的属性不存在,则返回default的值,若没有设置default参数,则抛出AttributeError异常。以下为该函数的语法:
 

getattr(object, name[, default])
 
object -- 对象
 
name -- 字符串,对象属性。
 
default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。
 
返回值:返回对象属性值。

>>> class People:
...     name = 'zth'
...     age = 20
...
>>>
>>> a= People()
>>>
>>>
>>> getattr( a ,'name')
'zth'
>>>
>>> getattr( a ,'class',5)
5
>>>
>>> getattr( a ,'class')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'class'

7 . setattr()

setattr( )函数对应函数getatt(),用于设置指定属性的值,若指定的属性不存在则新建属性并赋值。以下为该函数的语法:

setattr(object, name, value)
 
object -- 对象。
 
name -- 字符串,对象属性。
 
value -- 属性值。
 
返回值:无

 

>>> class People:
...     name = 'zth'
...
>>>
>>>
>>> a = People()
>>>
>>> setattr(a, 'name','en')
>>>
>>> setattr(a, 'age','20')
>>>
>>> getattr(a,'name')
'en'
>>>
>>> a.age
'20'

8.  delattr()

delattr( )函数用于删除属性,若属性不存在则抛出 AttributeError 异常。以下为该函数的语法:

delattr(object, name)
object -- 类名。
name -- 必须是对象的属性。
返回值:无
delattr(x, 'foobar') 相等于 del x.foobar。

 

>>> class  People:
...     name = 'zth'
...     age = 20
...
>>>
>>> s = People()
>>>
>>> s.name
'zth'
>>>
>>>
>>> delattr(People, 'name')
>>>
>>> s.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'name'
>>>
>>> del People.age
>>>
>>> s.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'age'

猜你喜欢

转载自blog.csdn.net/qq_41573234/article/details/82316207
今日推荐