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

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个方法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 1、abs() 描述: 函数返回数字的绝对值 语法:abs() 参数:x--数值表达式,可以是整数,浮点数,...
    清清子衿木子水心阅读 401评论 0 0
  • 包(lib)、模块(module) 在Python中,存在包和模块两个常见概念。 模块:编写Python代码的py...
    清清子衿木子水心阅读 3,798评论 0 27
  • 有些话聊着聊着就死了,有些人看着看着就打了 笔者从小到大都是一名话题终结能力达十级的高手, 每次总是能把聊得火热的...
    Timsou阅读 212评论 0 0
  • 前言:大家按照步骤从头看到尾,末尾有常见错误解决办法,如果有其他问题,大家先看错误提示,根据提示自行百度,很多问题...
    了尘兰若阅读 14,358评论 7 9
  • 人生八苦中,生老病死大概是我们所有人都需要面对的问题,尤其是对死亡的恐惧。基于对这方面的解析,斯坦福大学的一位教授...
    阿楠z阅读 128评论 3 0