python带下划线的方法,Python()-类的专有方式之双下划线方式

1. __call__() 方式

工具+() 可以直接挪用__call__()方式 , 类似通俗函数的挪用

classCallTest(object):def __init__(self):print('I am __init__')def __call__(self):print('I am __call__')returnTruedefrun(self):print('I am run')returnTrue

obj=CallTest()

obj.run()#挪用通俗方式 工具.func_name()

obj() #挪用__call__()方式, 直接 工具()

打印效果:

I am __init__

I am run

I am __call__

可以看到,obj这个工具被实例化出来,若是要挪用__call__方式的话,直接obj(),即可挪用并返回效果。obj就类似一个函数地址,obj()即执行这个函数。

2. __init__() 方式

组织函数,在生成工具时挪用

===========================

__getattr__, __setattr__, __delattr__

1. 挪用工具的一个不存在的属性时会触发__getattr__方式

2. 删除工具的一个属性的时刻会触发__delattr__方式

3. 设置工具(增添/修改)属性会触发__setattr__方式

设置工具属性和删除工具属性会触发__setattr__ 和 __delattr__ 方式,但要注重的是,在挪用这两个方式时,方式内部必须操作类的属性字典,否则会造成无限递归

3. __getattr__() 方式

—-挪用(获取)工具属性

classFoo:

a= 1

def __getattr__(self, item):print('run __getattr__')

f=Foo()print(f.a) #属性存在,就不会触发__getattr__()方式#>> 输出: 1

print(f.b) #只有在使用点挪用属性且属性不存在的时刻才会触发,而且返回None#>> 输出: run__getattr__#>> 输出: None

4. __delattr__() 方式

—-删除工具属性

classFoo:def __delattr__(self, item):print('run __delattr__')#del self.item # 这样会造成无限递归

self.__dict__.pop(item)

f=Foo()

f.a= 3

print(f.__dict__) #>> 输出: {'a': 3}

print(f.a) #>> 输出: 3

del f.a #>> 输出: run __delattr__

print(f.a) #>> 报错: AttributeError: 'Foo' object has no attribute 'a'

5. __setattr__() 方式

—-设置属性: 增添工具属性, 修改工具属性

classFoo:

a= 1

def __setattr__(self, key, value):print("run __setattr__")

f=Foo()#没有赋值,什么都不会发生

f.c= 200 #若是增添类属性, 触发触发__setattr__()方式#>> 输出: run__setattr__

f.a= 2 #若是修改类属性, 触发触发__setattr__()方式#>> 输出: run __setattr__

实例化工具传参,会触发__getattr__方式

classFoo:

a= 1

def __init__(self, b):

self.b= b #赋值属性操作

def __setattr__(self, key, value):print("run __setattr__")

f= Foo(100) #若是实例化的时刻传入参数举行赋值属性操作, 触发__setattr__()方式#>> 输出: run __setattr__

设置属性时, 方式内部必须操作类的属性字典

classFoo:

a= 1

def __setattr__(self, key, value):#self.key = value # 增添/修改类属性,会触发__setattr__()方式,若是这个操作在setattr方式内部,会造成无限递归

self.__dict__[key] = value #使用这种方式会完成增添/修改类属性的操作

print("run __setattr__")

f=Foo()

f.y= 3 #增添/修改类属性,挪用__setattr__()方式#>> 输出: run __setattr__

print(f.__dict__)#>> 输出: {'y': 3}

当我们重写__setattr__()方式后,方式内部若是不举行属性字典的操作,那么除非直接操作属性字典,否则永远无法完成赋值

classFoo:def __setattr__(self, key, value):print("run __setattr__")

f=Foo()

f.y= 3 #设置工具属性,挪用__setattr__()方式,而__setattr__()方式什么都没干,以是完成不了工具的设置属性操作#>> 输出: run __setattr__

print(f.__dict__)#>> 输出: {}

print(f.y) #完成不了赋值#>> 报错: AttributeError: 'Foo' object has no attribute 'y'

理解了__setattr__()方式的原理,我们就可以行使 __setattr__()方式 实现我们自定义的功效

classFoo:

a= 1dic= {} #自定义一个空字典

def __setattr__(self, key, value):

self.dic[key]=valueprint("run __setattr__")

f=Foo()

f.y= 3

#>> 输出: run __setattr__

print(f.dic) #给类变量dic添加键值对#>> 输出: {'y': 3}

print(f.__dict__) #类属性不发生转变#>> 输出: {}

一个小示例:

classFoo:def __init__(self, dic):

self._dic=dicdef __getattr__(self, item):

val=self._dic[item]ifisinstance(val, dict):

a=Foo(val)return a #重点: 又返回一个工具

else:returnval

dic= {'k1': 'v1', 'k2': 'v2'}

dic=Foo(dic)print(dic.k1)#>>输出: v1

print(dic.k2)#>>输出: v2

dic= {'k1': {'k2': 'v2'}}

dic=Foo(dic)print(dic.k1)#>>输出: 一个工具 <__main__.foo object at>

print(dic.k1.k2) #工具可以继续点(.)取属性操作#>>输出: v2

原理:

Foo(dic)实例化一个工具, dic.k1触发__getattr__()方式, val={‘k2’: ‘v2’},当val值为一个字典工具时,if条件建立, 返回一个以val字典为参数的工具,就是说: dic.k1 == Foo({‘k2’: ‘v2’}),这个工具可以继续通过点(.)挪用工具的属性,若是有多层嵌套,一直循环下去

接着上面的例子继续:

defv2(arg):returnarg

dic= {'k1': {'k2': v2}}

dic=Foo(dic)

ret= dic.k1.k2(100)print(ret)#>> 输出: 100

6. __getattribute__() 方式

长得和__getattr__那么像,那么__getattribute__与之有什么关系呢?

classFoo:

a= 1

def __init__(self, x):

self.x=xdef __getattribute__(self, item):print('不管属性[%s]是否存在,我都市执行' %item)

f= Foo(100)print(f.a)#>>输出: 不管属性[a]是否存在,我都市执行#>>输出: None

print(f.b)#>>输出: 不管属性[b]是否存在,我都市执行#>>输出: None

print(f.x)#>>输出: 不管属性[x]是否存在,我都市执行#>>输出: None

当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

classFoo:def __getattr__(self, item):print('run __getattr__')def __getattribute__(self, item):print('不管属性[%s]是否存在,我都市执行' %item)#raise AttributeError('啦啦啦啦')

f=Foo()#print(f.a)#>>输出: 不管属性[a]是否存在,我都市执行#>>输出: None

print(f.a) #打开注释,手动抛错: raise AttributeError('q')#>>输出: 不管属性[a]是否存在,我都市执行#>>输出: run __getattr__#>>输出: None

7. super()

super 的事情原理如下:

defsuper(cls, inst):

mro= inst.__class__.mro()return mro[mro.index(cls) + 1]

其中 cls 代表类, inst 代表实例, super 函数做了两件事:

1. 获取实例工具 inst 的类的 MRO 列表

2. 查找 cls 在当前 MRO 列表中的 index ,并返回它的下一个类,即 mro[index + 1]

当使用 super(cls, inst) 时, Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类. 可以看出, 事实上 super 函数和父类没有实质性的关联.

原文链接:https://www.cnblogs.com/zhzhlong/p/12854255.html

本站声明:网站内容来源于网络,若有侵权,请联系我们,我们将及时处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值