类的内置方法与属性

python中的类在定义时就包含了一系列的专有方法和内置属性,这些内置的属性和方法在操作类时非常便利

内置属性

__name__

显示类名,注意和显示module名称的__name__的区别

class Animal: pass


print(__name__)  # 显示模块名 __main__
print(Animal.__name__)  # 显示类名 Animal

__bases__

显示父类信息

class Animal: pass


class Life: pass


# Dog继承Animal与Life
class Dog(Animal, Life): pass


print(Dog.__bases__)  # (<class '__main__.Animal'>, <class '__main__.Life'>)

__module__

类所在的模块,如果是直接运行脚本,值为__main__,如果类作为模块被导入,值为包名.模块名,新建一个package human,然后在teacher模块中定义一个类Teacher

class Teacher(): pass

脚本中导入teacher模块

import human.teacher

t = human.teacher.Teacher()
print(t.__module__)  # 作为模块被导入,__module__值为human.teacher

直接在脚本中定义一个类Animal

class Animal: pass


print(Animal.__module__) # 作为入口使用,__module__值为__main__

__dict__

返回一个包含类中所有属性的字典,包含类属性,实例属性,私有属性和内置属性

class Animal:
    _sex = ""
    age = ""

    def __init__(self):
        self.name = ""


print(Animal.__dict__)  # name属性由于实例化时创建,所以此处是得不到的
dog = Animal()
print(dog.__dict__)  # 这样就可以取到name属性了

__mro__

python中的类是多继承的,如果一个子类同时继承多个父类,那么访问父类中的方法,将按照MRO顺序访问,可以输出__mro__来看看查找顺序

class A: pass

class B(A): pass

class C(A): pass

class D(A): pass

class E(B, C, D): pass

print(E.__mro__) # E,B,C,D,A

类的专有方法

__new__()__init__()

__new__() 是构造方法,用于产生实例化对象,必须返回一个对象
__init__() 初始化方法,负责对实例化对象进行属性值初始化,此方法必须返回None

在实例化对象时,先调用__new__()创建一个空对象,然后再调用__init__()初始化对象,__init__()之前介绍过,可以给实例增加实例属性

class Animal:
    def __new__(cls, *args, **kwargs):
        print("生产实例化对象")
        return object.__new__(cls)

    def __init__(self):
        print("初始化对象")
        # 增加实例属性
        self.sex = ""
        self.age = ""


dog = Animal()

python类与objective-c语言很像,所有的类均继承object

__str__()__repr__()

调用print()repr()输出对象时会调用对应的__str__()__repr__(),必须返回一个string对象,demo中以__str__()为例,__repr__()与其完全一致,可以鸡贼的定义__repr__ = __str__保持一直

class Animal:

    def __str__(self):
        return "\033[1;31;32m[Info]  " + super(object, Animal).__str__()

    __repr__xxz = __str__


dog = Animal()
print(dog)

打印绿色字体的类信息

__call__()

__call__()可以让类对象像函数一样执行,本质上,函数就是一个拥有call方法的对象

class Animal:

    def __call__(self, *args, **kwargs):
        print("wang wang wang!")


dog = Animal()
dog()  # wang wang wang!

__del__

调用__del__会将对象的引用计数置0, 并被垃圾回收器回收, 当程序结束调用时也会调用此方法

class Animal:
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print("删除对象",self.name)


dog = Animal("dog")
cat = Animal("cat")
del dog  # 调用时删除dog对象
# 程序运行结束 自动删除cat对象

注:python中的垃圾回收策略是引用计数为主, 分代收集为辅

__iter__()__next__()

python中的list,tuple,setdictionary都可以通过iter()转换为迭代器,然后通过next()一次取出其中一个元素, 迭代器其实就是通过调用内置的__iter__()__next__()实现,而类作为一种类型,自然也可以实现迭代器,只需要实现__iter__()__next__()即可

class Animal:
    name = ["dog", "cat"]

    def __iter__(self):
        print("获取类迭代器对象")
        return self

    def __next__(self):
        if len(self.name) > 0:
            return self.name.pop()
        else:
            return StopIteration("没有更多元素")


b = iter(Animal())  # 获取类迭代器对象
print(next(b))  # cat
print(next(b))  # dog
print(next(b))  # 没有更多元素

注意:实现__next__()一定要判断边界

__getitem__()__setitem__()__delitem__()

除了将类作为迭代器,也可以将类作为一个list或者dictionary来访问,只需要实现相应的方法即可

class Animal:
    voice = {"dog": "wang", "cat": "miao"}

    def __setitem__(self, key, value):
        print("新增动物{} 叫声:{}".format(key, value))
        self.voice[key] = value

    def __getitem__(self, item):
        if self.voice.get(item) is None:
            return KeyError("{key}不存在".format(key=key))
        else:
            print("{}的叫声是{}".format(item, self.voice[item]))
            return self.voice[item]

    def __delitem__(self, key):
        if self.voice.get(key) is None:
            return KeyError("{key}不存在".format(key=key))
        else:
            print("删除{key}成功".format(key=key))
            del self.voice[key]


a = Animal()
a["dog"]  # 访问 dog的叫声是wang
a["bridge"] = "zhi"  # 设置 新增bridge 值:zhi
del (a["cat"])  # 删除 删除cat成功

注意:实现时一定要判断key的存在,否则会造成except

__getattr__()__setattr__()__delattr__()

访问、设置和删除对象属性时会触发相应方法

class Animal:
    def __init__(self):
        self.age = 25
        self.sex = "公"

    def __getattr__(self, item):
        print("要访问的属性是" + item)
        return item

    def __setattr__(self, key, value):
        print("要设置的属性是{key},值为{value}".format(key=key, value=value))

    def __delattr__(self, item):
        print("要删除的属性是" + item)


singleDog = Animal()
print(singleDog.age)
del singleDog.age

__getatrribute__()

__getatrribute__()是一个属性访问截断器,当访问对象的属性时,会优先触发这个方法,访问一个属性的顺序如下

  1. 实例的__getattribute__()方法
  2. 实例对象字典
  3. 实例所在类字典
  4. 实例所在类的父类(MRO顺序)字典
  5. 实例所在类的getattr
  6. 报错

demo示例如下

class A:
    age = 10


class B(A):
    name = "狗"

    def __init__(self):
        self.sex = "公"

    def __getattribute__(self, item):
        print("1.进入__getattribute__(), 查找的属性", item)
        return super(object, B).__getattribute__(item)

    def __getattr__(self, item):
        print("5.进入__getattr__(), 查找的属性", item)
        # 6.没有找到 应该报错


b = B()
print(b.__dict__)  # 2.在实例的字典中查询
print(B.__dict__)  # 3.在实例所在类字典中给查询
print(A.__dict__)  # 4.在实例父类类字典查询
print(b.name)

传送门之MRO与C3算法

__enter__()__exit__()

重写这两个方法可以允许对一个类对象使用with方法.

class A:
    def __enter__(self):
        print("open文件")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("退出")


with A() as a:
    # do something
    pass

总结

从上面的方法可以看出一些共同点,在此整理一下

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

推荐阅读更多精彩内容

  • 内置函数Python解释器内置了许多功能和类型,总是可用的。他们是按字母顺序列在这里。 abs(x)返回一个数的绝...
    uangianlap阅读 1,234评论 0 0
  • 本文为《爬着学Python》系列第十四篇文章。 中间因为工作原因隔了好久没有更新,现在稳定很多,会陆续开始更新。不...
    SyPy阅读 12,098评论 1 10
  • pyton review 学习指南 https://www.zhihu.com/question/29138020...
    孙小二wuk阅读 1,046评论 0 2
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,739评论 0 10
  • 小编我最近在减肥,不仅到处去搜刮一些低脂低卡的东西,和朋友出去吃饭,也会说不吃这个不吃那个,热量高不吃,脂肪高不吃...
    部落直播阅读 832评论 0 1