Python 特殊方法
以双下划线开头和结尾的方法称为特殊方法,__xxxx__。
在定义类对象时,经常会重写一个或多个特殊方法,例如__init__。通常特殊方法都是自动调用的。
__dict__ 获取对象信息
# __dict__ 查看对象信息
class Animal(object):
def __init__(self):
self.name = 'Animal'
def eat(self):
print('eat')
animal = Animal()
print(Animal.__dict__)
'''
结果:
{
'__module__': '__main__',
'__init__': <function Animal.__init__ at 0x000001CE58A28D90>,
'eat': <function Animal.eat at 0x000001CE58A28E18>,
'__dict__': <attribute '__dict__' of 'Animal' objects>,
'__weakref__': <attribute '__weakref__' of 'Animal' objects>,
'__doc__': None
}
'''
print(animal.__dict__)
# {'name': 'Animal'}
__len__ 获取实例对象长度
# __len__ 返回对象长度
class Animal(object):
def __init__(self, name):
self.name = name
def __len__(self):
return len(self.name)
dog = Animal('dog')
elephant = Animal('elephant')
print(len(dog)) # 3
print(len(elephant)) # 8
__iter__ 和 __next__ 使实例对象可迭代
# __iter__ 和 __next__ 使实例对象可迭代
class Student(object):
def __init__(self):
self.book = ['Math','English','Chinese','Physical']
def __iter__(self):
self.count = 0
self.book_list_len = len(self.book)
return self # 通常返回的是self
def __next__(self):
if self.count < self.book_list_len:
book_name = self.book[self.count]
self.count += 1
return book_name
else:
raise StopIteration # 停止迭代
xiaoming = Student()
for i in xiaoming:
print(i)
__add__ 运算符重载
算术运算符可以用于自定义类对象的实例对象,必须在自定义类对象中实现标准算术运算符对应的以下特殊方法:
- +对应的特殊方法是__add__()和__radd__();
- -对应的特殊方法是__sub__()和__rsub__();
- *对应的特殊方法是__mul__()和__rmul__();
- /对应的特殊方法是__truediv__()和__rtruediv__();
- //对应的特殊方法是__floordiv__()和__rfloordiv__()
# 实例对象实现加法
class Myclass(object):
def __init__(self, data):
self.data = data
def __add__(self, other): # other指的是加号右边的对象
return self.data + other.data
a = Myclass(10)
b = Myclass(20)
print(a + b)
__str__和__repr__ 输出字符
# __str__ 和 __repr__
class Myclass(object):
def __init__(self, data):
self.data = data
def __str__(self):
return self.data
def __repr__(self):
return self.data
a = Myclass('123')
print(a) # 123
print(str(a)) # 123
print(repr(a)) # 123
str()和repr()都返回对象字符串,其区别在于:
- str()是给用户看的,显示更加友好。
- repr()是给程序开发者看的,为调试服务的。
>>> str('Hello!\nWorld')
'Hello!\nWorld'
>>> print(str('Hello!\nWorld'))
Hello!
World
>>> repr('Hello!\nWorld')
"'Hello!\\nWorld'"
>>> print(repr('Hello!\nWorld'))
'Hello!\nWorld'
__new__ 创建实例方法
当使用“类名(实参)”创建实例对象时,python解析器的主要处理过程包括:
- 调用特殊方法__new__()创建实例对象。
- 调用特殊方法__init__()对创建的实例对象进行初始化。
__init__中接收的self其实就是__new__中返回的对象。
# __new__ 创建实例调用方法
class Animal(object):
def __new__(cls, *args, **kwargs):
new_object = object.__new__(cls)
print('New object id is %s' % id(new_object))
return new_object
def __init__(self, name):
print('Init object id is %s' % id(self))
dog = Animal('123')
'''
结果:
New object id is 2650305182240
Init object id is 2650305182240
'''
__del__ 对象删除方法
可以定义__del__来执行当对象被删除时所需的操作。
# __del__ 删除方法
import time
class Animal(object):
def __init__(self, name):
self.name = name
def __del__(self):
print('%s对象被删除!' % self.name)
dog = Animal('dog')
print(dog.name)
print('dog对象会在3秒后被删除')
time.sleep(3) # 程序结束,必定会删除对象
==当引用计数器为0时,对象不会立即被销毁(垃圾回收),所以__del__执行的时间也是不确定的。==
__getattr__ 获取对象属性或方法
# __getattr__
class Animal(object):
def __init__(self, name):
self.name = name
def __getattr__(self, item):
if item == 'name':
return self.name
elif item == 'say_name':
return self.say_hi
else:
raise AttributeError('No attribute "%s"' % item)
def say_hi(self, value):
print('Hi %s!' % value)
dog = Animal('dog')
print(dog.name) # dog
dog.say_hi('cat') # Hi cat!
print(dog.age) # AttributeError: No attribute "age"
__getitem__、__setitem__、__deltitem__ 索引设置
使实例对象实现像列表或者字典索引操作的三个方法。
# __getitem__、__setitem__、__delitem__
class Animal(object):
def __init__(self):
self.data = {}
def __getitem__(self, item):
return self.data.get(item)
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
dog = Animal()
dog['name'] = 'dog'
print(dog['name'])
del dog['name']
print(dog['name'])
__call__ 函数调用
使实例对象可以像函数一样被调用。
# __call__
class Animal(object):
def __call__(self, *args, **kwargs):
print(args)
print(kwargs)
dog = Animal()
dog(18, 'yellow', name='dog')
print(callable(dog))
'''
结果:
(18, 'yellow')
{'name': 'dog'}
True
'''
==可以通过函数callable()来判断对象是否可以被调用。==
__doc__ 文档字符串
与函数的文档字符串类似,类对象的第一行字符串表示文档字符串。它是对类对象的功能的简要描述。
# __call__
class Animal(object):
'''这是一个动物类'''
pass
dog = Animal()
print(Animal.__doc__)
print(dog.__doc__)
'''
结果:
这是一个动物类
这是一个动物类
'''
__slots__ 限制实例对象属性或方法
# __slots__
class Animal(object):
def __init__(self):
self.name = 'animal'
__slots__ = ('age', 'eat', 'name')
dog = Animal()
print(dog.name) # animal
dog.age = 3
def eat(self):
print('%s eat!' % self.name)
Animal.eat = eat
dog.eat() # animal eat!
Animal.color = 'withe' # 对于类对象没有影响
dog.color = 'withe' # AttributeError: 'Animal' object has no attribute 'color'
__slots__对于子类的实例对象是不生效的,如果子类也有__slots__,那么子类的对象可用实例属性或方法则为父类__slots__加子类__slots__。