在python中以双下划线开头,双下划线结尾的内置函数
使用魔法函数可以增强对象的类型 例如:
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
#实现了这个魔法函数,就实现了迭代类型,可迭代类型的作用就是可以直接使用for循环去调用
company = Company(['tom', 'alice','jim'])
company1 = company[ :2]
for em in company1:
print(em)
这样就会增强对象的类型,使对象可迭代,可序列化
常见的特殊方法
1、重写repr方法
object 类提供的repr()方法总是返回该对象实现类的“类名+object at+ 内存地址”值,这个返回值并不能真正实现“自我描述”的功能,因此如果用户需要自定义类能实现“自我描述”的功能,就必须重写repr()方法。
class Computer:
def __init__(self, name, price):
self.name = name
self.price = price
im = Computer('鼠标', 29.8)
print(im)
print() 函数 只能在控制台打印字符串,而computer实际是一个内存中的对象,使用该方法输出的Computer对象实际上输出的是Coputer对象的repr()方法的返回值。
<__main__.Computer object at 0x000000000110E4E0>
repr()是python类中一个特殊的方法,由于object类已提供了该方法,而所有的python类都继承于object,因此所有的python对象都具有repr()方法
class Apple:
#实现构造器:
def __init__(self, color, weight):
self.color = color
self.weight = weight
#重写__repr_()方法
def __repr__(self):
return "Apple[color= " + self.color+",weight = " + str(self.weight) + "]"
a = Apple("红色", 5)
print(a)
输出
Apple[color= 红色,weight = 5]
2、del()析构函数,用于垃圾回收,在后边的文章中有详细介绍
3、dir()方法
对象的dir()方法用于列出该对象内部所有的属性(包括方法)名,该方法将会返回包含所有属性(方法)名的序列。
当程序对某个对象执行dir(object)函数时,实际上就是将该对象的dir()方法返回值进行排序,然后包装成列表。
4、dict属性
dict属性用于查看对象内部存储的所有属性名和属性值组成的字典,通常程序直接使用该属性即可。程序使用dict属性既可以查看对象的所有内部状态,也可以通过字典的语来访问或修改指定属性的值。
class Item:
def __init__(self, name, price):
self.name = name
self.price = price
im = Item('鼠标', 100)
print(im.__dict__)
#通过__dict__来访问name 和 price 属性
print(im.__dict__['name'])
print(im.__dict__['price'])
im.__dict__['name'] = '键盘'
im.__dict__['price'] = 200
print(im.name)
输出
{'name': '鼠标', 'price': 100}
鼠标
100
键盘
5、getattr 和 setattr等
当程序操作(包括访问、设置、删除)对象的属性时,python系统会同样执行该对象特定的方法。
__getattribute__(self, name) 当程序访问对象的name属性时会被自动调用
__getattr__(self, name) 当程序访问对象的name属性且该属性不存在时被自动调用。
__setattr__(self, name, value) 当程序对对象的name属性赋值时被自动调用
__delattr__(self, name) 当程序删除对象的name属性时被自动调用
当python类的属性不存在时,通过重写上边的方法可以合成新属性
class Rectange(object):
"""docstring for Rectange"""
def __init__(self, width, height):
self.width = width
self.height = height
def __setattr__(self, name, value):
print('----设置%s属性-----' %name)
if name == "size":
self.width, self.height = value
else:
self.__dict__[name] = value
def __getattr__(self, name):
print('------读取%s属性-----' %name)
if name == 'size':
return self.width, self.height
else:
raise AattributeError
def __delattr__(self, name):
print('----删除%s属性----' %name)
if name == 'size':
self.__dict__['width'] = 0
self.__dict__['height'] = 0
当size属性不存在时,会调用getattr()方法
rect = Rectange(3, 4)
print(rect.size)
输出
----设置width属性-----
----设置height属性-----
------读取size属性-----
(3, 4)
当访问的属性存在时,不会调用getattr()方法
rect.size = 6, 8
print(rect.width)
输出
----设置size属性-----
----设置width属性-----
----设置height属性-----
6
如果程序在读取,设置属性之前要进行某种拦截处理(比如检查数据是否合法之类的),也可以通过重写setattr()或getattribute方法来实现。
class User(object):
"""docstring for User"""
def __init__(self, name, age):
self.name = name
self.age = age
#重写__setattr__()方法对设置的属性进行检查
def __setattr__(self, name, value):
#如果正在设置name属性
if name == 'name':
if 2<len(value)<= 8 or len(value) >8 :
self.__dict__['name'] = value
else:
raise ValueError('name的长度必须在2-8之间')
elif name == 'age':
if 10 < value < 60:
self.__dict__['age'] = value
else:
raise ValueError('age值必须在10-60之间')
u = User('bobo', 20)
print(u.name)
print(u.age)
u.name = 'c'
6、与序列相关
序列最重要的特征就是可以包含多个元素
__len__(self) 返回值决定序列中元素个数
__getitem__(self, key) 该方法获取指定索引对象的元素。key应该是整数值或者slice对象,否则会引发KeyError异常
__contains__(self, item) :该方法可以判断序列是否包含指定元素 if in 的内部实现机制就是通过该魔术方法
__setitem__(self, key, value) 该方法设置指定索引对应的元素。key应该是整数值或者slice对象,否则会引发KeyError异常
__delitem__(self, key): 该方法删除指定索引对应的元素
如果程序要实现不可变序列,只要实现上面三个方法即可,如果要实现可变序列,则需要实现上面的5个方法