Python除了自定义私有变量和方法外,还可以定义专有方法。专有方法是在特殊情况下或使用特殊语法时由python调用的,而不是像普通方法一样在代码中直接调用。看到形如__XXX__的变量或函数名时就需要注意下,这在python中是有特殊用途的
定义一个 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
如果想要将一个类用于 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
Fib 实例虽然能够作用于 for 循环,和 list 有点像,但是不能将它当成 list 使用。比如取第3个元素:
>>> Fib()[3]
Traceback (most recent call last):
File "", line 1, in
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
正常情况下,调用类的方法或属性时,如果类的方法或属性不存在就会报错。
定义Student类:
>>> class Student(object):
... def __init__(self):
... self.name = 'zth'
...
>>>
>>> s = Student()
>>>
>>> s.name
'zth'
>>>
>>> s.age
Traceback (most recent call last):
File "", line 1, in
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。
一个对象实例可以有自己的属性和方法,调用实例的方法时使用 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
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 "", line 1, in
AttributeError: 'People' object has no attribute 'class'
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'
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 "", line 1, in
AttributeError: 'People' object has no attribute 'name'
>>>
>>> del People.age
>>>
>>> s.age
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'People' object has no attribute 'age'