python中的魔法函数

在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)
7129460-318c414af0609cef.png
image.png

这样就会增强对象的类型,使对象可迭代,可序列化

常见的特殊方法

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()方法返回值进行排序,然后包装成列表。

7129460-9025f71c8b79d65f.png
image.png

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、getattrsetattr
当程序操作(包括访问、设置、删除)对象的属性时,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个方法

猜你喜欢

转载自blog.csdn.net/weixin_33693070/article/details/87114894