Python魔术方法

一、常用魔术方法

特点:不需要人工调用,在特定的时刻自动执行.

1.__ init __ :初始化魔术方法(最重要)

  • 触发时机:实例化对象之后触发
  • 作用:为对象添加所属成员
  • 参数:一个self接受当前对象,其他的参数根据实例化的传参决定
  • 返回值:无
  • 注意事项:无
    代码:
class Human:
    def __init__(self,kindname,petname):
        self.sex='男'
        self.age=1
        self.name=kindname
        self.petname=petname

if __name__=='__main__':
    # 创建一个对象
    one=Human('刘佳琪','小妮子')
    # 输出对象的成员
    print(one.__dict__)

输出结果:

{'sex': '男', 'age': 1, 'name': '刘佳琪', 'petname': '小妮子'}

2.__ new __:构造方法

  • 触发时机:实例化对象的时候触发
  • 作用:管理控制对象的生成
  • 参数:一个cls接收当前类,其他的参数根据实例化的参数决定
  • 返回值:可有可无 没有返回值,实例化结果为None
  • 注意事项:new 魔术方法跟init的魔术方法的参数一致(除了第一个)
    代码:
class Human:
    def __new__(cls, sex):
        # 如果生女就返回对象,如果生男就不管
        if sex=='女':
            return object.__new__(cls)
        else:
            return None

if __name__=='__main__':
    # 创建一个对象
    one=Human('男')
    # 输出对象的成员
    print(one)

输出结果:

None

3.__ del __:析构方法

  • 触发时机:对象被系统回收的时候自动触发(del不一定触发)
  • 作用:回收程序使用过程的信息和变量等,在操作数据库的时候最终关闭数据库
  • 参数:一个self接收当前对象
  • 返回值:无
  • 注意事项:无
    代码:
class Human:
    def __del__(self):
        print('del方法被触发了')

if __name__=='__main__':
    # 创建一个对象
    one=Human()
    # 输出对象的成员
    print(one)

4.__ call __:

  • 触发时机:将对象当做函数调用的时候自动触发
  • 作用:常用于归结类/对象的操作步骤,方便后期调用
  • 参数:一个self接收当前对象,其余的参数根据需求添加
  • 返回值:可以有可以无
  • 注意事项:无
    代码:
class MakeCake:
    def huomian(self):
        print("和面")

    def fajiao(self):
        print('发酵')

    def honbei(self):
        print('烘焙')

    def qiexinzhuan(self):
        print('切形状')

    def fangshuiguo(self):
        print('放水果')

    def __call__(self,name):
        self.huomian()
        self.fajiao()
        self.honbei()
        self.qiexinzhuan()
        self.fangshuiguo()
        print('给{}做的蛋糕已经完成'.format(name))

if __name__=='__main__':
    cake=MakeCake()
    cake('张三')

输出结果:

和面
发酵
烘焙
切形状
放水果
给张三做的蛋糕已经完成

5.__ len __:

  • 触发时机:使用len函数检测对象的时候自动触发
  • 作用:使用len可以检测对象中某个数据的信息
  • 参数:一个self接收当前对象
  • 返回值:必须有返回值,必须是整型
  • 注意事项:len检测什么,由开发者自定定
    代码:
class car:
    # 成员属性
    color='黑色'
    weight='2T'
    grand='奥利奥'
    circle=['左前轮','右前轮','左后轮','右后轮','备胎']

    # 成员方法
    def playmusic(self):
        print('你存在我深深的脑海')

    def move(self):
        print('请注意倒车,请注意倒车')

    def __len__(self):
        num=len(self.circle)
        return num

# 实例化一个对象
mycar=car()

# 定义了len方法,就可以直接使用len计算这个类的长度
result=len(mycar)
print(result)

输出结果:

5

6.__ str __:

  • 触发时机:使用print打印对象的时候自动触发
  • 作用:可以定义打印对象显示的信息内容
  • 参数:一个self接受当前对象
  • 返回值:必须有,且必须是字符串
  • 注意事项:除了print之外,使用str()转换数据的时候也会触发
    代码:
class Human:
    # 成员属性
    color = '黄色'
    sex = '女'
    age = 18
    name = '史珍香'

    # 成员方法
    def __str__(self):
        # 重载魔术方法__str__(继承自object类)
        return self.name

    def eat(self):
        print('真香~')

    def smile(self):
        print('哈哈哈哈哈')

if __name__ == '__main__':
    wuman = Human()
    # 第一种触发方式
     print(wuman)

输出结果:

史珍香

7.__ repr __:

  • 触发时机:在使用repr转换对象的时候自动触发
  • 作用:可以设置repr函数操作对象的结果
  • 参数:一个self接受当前对象本身
  • 返回值:必须有,且必须是字符串
  • 注意事项:在正常情况下repr和str魔术方法是完全一样的(字符串中的str和repr魔术方法就不一样)
    代码:
class Human:
    # 成员属性
    color = '黄色'
    sex = '女'
    age = 18
    name = '史珍香'

    # 成员方法
    # __repr__魔术方法,在通常的类中repr重载相当于str也被重载
    def __repr__(self):
        print('repr方法被触发')
        return self.name

    def __str__(self):
        return 'str被触发'
    # 所有类默认都存在一个等式
    # __str__=__repr__ 将repr的方法赋值给str方法 完全一样

    def eat(self):
        print('真香~')

    def smile(self):
        print('哈哈哈哈哈')

human=Human()
print(human)
print(repr(human))

输出结果:

str被触发
repr方法被触发
史珍香

str和repr的区别:

mysong='我\n喜欢\t你'
print(mysong)
print(str(mysong))
print(repr(mysong))

输出结果:


喜欢 你

喜欢 你
'我\n喜欢\t你'

8.__ bool __:

  • 触发时机:在使用bool()转换对象的时候自动触发
  • 作用:用于检测对象成员的信息
  • 参数:一个self接受当前对象
  • 返回值:必须有,且必须是bool值
  • 注意事项:任何对象在使用bool方法的时候默认都是True
    代码:
class man:
    sex='男'
    age=18
    married='已婚'

    def __bool__(self):
        print('bool方法已经被触发')
        if self.married=='已婚':
            return True
        else:
            return False

    def smkoking(self):
        print('多数男人都抽烟~')

    def say(self):
        print('男人都是甜言蜜语')
man=man()
print(bool(man))

输出结果:

bool方法已经被触发
True

9.__ format __:

  • 触发时机:在使用format()转换对象的时候自动触发
  • 作用:用于格式化输出信息
  • 参数:一个self接受当前对象,arg接受格式
  • 返回值:必须有,且必须为字符串格式
  • 注意事项:可以不是格式,直接作为填充输出
    代码:
class Girl:
    # 成员属性
    name='熊楮墨'
    sex='女'
    age=18

    # 成员方法
    def __format__(self,arg):
        # arg是接受限定符号的字符串
        # 1.接受限定符号
        flag=arg
        print('限定符号:',flag)
        # 2.拆分限定符号
        fillchar=flag[0] # 填充字符
        align=flag[1] # 对齐方式
        length=int(flag[2:]) # 字符长度
        # 3.根据不同的符号进行不同的填充操作
        # 判断对齐方式
        if align=='>':# 右对齐
            newname=self.name.rjust(length,fillchar)
            return newname
        elif align=='^':
            newname=self.name.center(length.fillchar)
            return newname
        elif align=='<': # 左对齐
            newname=self.name.ljust(length,fillchar)
            return newname

    def shopping(self):
        print('买买买~~')

    def eat(self):
        print('吃烧烤~~')

# 实例化一个对象
girl=Girl()
action='我想和{:@>10}去逛街'
print(action.format(girl))

输出结果:

限定符号: @>10
我想和@@@@@@@熊楮墨去逛街

二、属性相关的魔术方法

就是获取成员,删除成员,修改成员相关联的魔术方法

5个属性相关的魔术方法:

  • __ getattr __
  • __ setattr __
  • __ delattr __
  • __ getattribute __
  • __ dir __

属性访问的顺序!:

  • 1.调用__ getattribute __
  • 2.【调用数据描述符】
  • 3.调用当前对象的所属成员
  • 4.调用类的所属成员
  • 5.【调用非数据描述符】
  • 6.调用父类的所属成员
  • 7.调用getattr

注意:以上步骤是调用某个成员的访问顺序以及优先级,前面的能获取成员,就不会向后查找

1.__ getattribute __

  • 触发时机:访问对象成员的时候就会触发,无论成员是否存在
  • 作用:可以在用户获取数据的时候进行数据处理等操作
  • 参数:一个self接受当前对象,另外一个参数接受访问对象成员名称的字符串
  • 返回值: 有 不设定返回None
  • 注意事项:在当前魔术方法中禁止使用 当前对象.成员 的方式访问成员,会触发递归操作,必须借助object的getattribute来获取当前对象的成员变量
    代码:

class Human:
    # 添加成员属性(加入对象)
    def __init__(self):
        self.name='李斯'
        self.sex='男'
        self.age=18

    # 添加成员方法
    # 添加魔术方法__getattribute__
    def __getattribute__(self, item):
        # item接受的是访问成员的名称字符串
        # 一定不能使用当前对象的成员访问,会再次触发当前魔术方法进入递归循环
        result=object.__getattribute__(self,item)
        # 隐藏用户名(自己的惭怍)
        newname=result[0]+'*'+result[-1]
        # 返回的数据
        return newname

    def eat(self):
        print('一天三顿小烧烤')

    def drink(self):
        print('喝啤酒')

# 实例化对象
ls=Human()
print(ls.name)

输出结果:

李*斯

2.__ getattr __

  • 触发时机:访问不存在对象成员的时候自动触发
  • 作用:防止访问不存在的成员的时候报错!为不存在的成员定义值
  • 参数:一个self接受当前对象,另外一个参数接受访问对象成员名称的字符串
  • 返回值:可有可无
  • 注意事项:无
    代码:
class Human:
    # 添加成员属性(加入对象)
    def __init__(self):
        self.name='李斯'
        self.sex='男'
        self.age=18

    def __getattr__(self, item):
        return '访问成员变量不存在'

    def eat(self):
        print('一天三顿小烧烤')

    def drink(self):
        print('喝啤酒')

# 实例化对象
ls=Human()
print(ls.name2)

输出结果:

访问成员变量不存在

3.setattr

  • 触发时机:添加对象成员或者修改对象成员的时候自动触发
  • 作用:可以限制或者管理对象成员的添加与修改操作
  • 参数:一个self接受当前对象,第二个接受设置的成员变量名称字符串 第三个接受设置的值
  • 返回值:无
  • 注意事项:在当前魔术方法中禁止使用当前对象.成员名=值得方式,会触发递归操作!
    代码:
class Human:
    # 添加成员属性(加入对象)
    def __init__(self):
        self.name='东方不败'
        self.sex='男'
        self.age=18

    def __setattr__(self, key, value):
        # 这样可以设置性别不修改
        if key=='sex':
            object.__setattr__(self, key,'男')
        else:
            object.__setattr__(self,key,value)

    def eat(self):
        print('一天三顿小烧烤')

    def drink(self):
        print('喝啤酒')

# 实例化对象
ls=Human()
print(ls.name)
ls.name='西门吹雪'
ls.sex='女'
print(ls.name)
print(ls.sex)

输出结果:

东方不败
西门吹雪

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

推荐阅读更多精彩内容