阅读源码的时候,经常看见hasattr
、getattr
、setattr
,感觉很酷炫的同时,也是不解其义,特此来说说道说道这三兄弟
getattr已经介绍过了,主要说说setattr和hasattr
hasattr(对象,属性名)
I、基本操作
- 1、查看对是不是该属性,返回值为boolean类型
- 2、 一个危险的Python函数,不推荐使用这篇文章说道hasattr会把@property装饰的方法隐藏掉,以至于使用第三方库的时候,不知道对方是否使用了这个装饰器,而造成错误。
- 3、但是这篇文章是三年前写的,这个问题已经被修复了。可以愉快的使用了,但是如果使用Python2x或者需要编写适配Python全系列的话,还是不要用太多
class Test:
@property
def name(self):
return "Despair"
@property
def age(self):
return 11
T = Test()
print(hasattr(T, 'name'))
print(getattr(T, 'name', None))
print(hasattr(T, 'age'))
print(getattr(T, 'age', None))
-----
True
Despair
True
11
II、速度效益
- 1、上面那篇文章说,hasattr内部实现是调用getattr,经过试验,这个也被改过了,hasattr的速度并不比getattr慢
from timeit import timeit
description = '''\
class Test:
@property
def name(self):
return 'Donald'
a = Test()
'''
stm = '''\
hasattr(a,'name')
'''
print(f'hasattr 执行10000次所需时间:{timeit(stmt=stm, setup=description, number=10000)}')
stm = '''\
getattr(a, 'name', None)
'''
print(f'getattr 执行10000次所需时间:{timeit(stmt=stm, setup=description, number=10000)}')
-----
hasattr 执行10000次所需时间:0.0015951709999999994
getattr 执行10000次所需时间:0.0016753230000000029
- 2、 可以看出来,运行时间hasattr还是略胜一筹,在Python3x中,hasattr还是可以愉快的玩耍的
setattr(对象,key, value)
I、基础操作
- 1、给对象添加一个属性,相当于在对象的__dict__中再添加一组键值对
- 2、如果是自己写的对象或者第三方的对象,是只可以直接使用
对象.__setattr__(key,value)
等效于setattr()。但是对自带的几种基本数据类型不起作用···具体原因,我目前不清楚
class Test:
def __init__(self):
self.name = "Donald"
def name(self):
return self.name
a = Test()
print(a.__dict__)
setattr(a, 'a', 'hello') # setattr()
print(a.__dict__)
a.__setattr__('b', 'world') #__setattr__()
print(a.__dict__)
*****
# 第三方模块
import requests
b = requests.session() # request的一个方法
print(b.__dict__)
b.__setattr__('a', 'hello')
print(b.__dict__)
------
# 新加的在最后面
{'headers': {'User-Agent': 'python-requests/2.19.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}, 'auth': None, 'proxies': {}, 'hooks': {'response': []}, 'params': {}, 'stream': False, 'verify': True, 'cert': None, 'max_redirects': 30, 'trust_env': True, 'cookies': <RequestsCookieJar[]>, 'adapters': OrderedDict([('https://', <requests.adapters.HTTPAdapter object at 0x120b6f0b8>), ('http://', <requests.adapters.HTTPAdapter object at 0x1212b3ef0>)])}
{'headers': {'User-Agent': 'python-requests/2.19.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}, 'auth': None, 'proxies': {}, 'hooks': {'response': []}, 'params': {}, 'stream': False, 'verify': True, 'cert': None, 'max_redirects': 30, 'trust_env': True, 'cookies': <RequestsCookieJar[]>, 'adapters': OrderedDict([('https://', <requests.adapters.HTTPAdapter object at 0x120b6f0b8>), ('http://', <requests.adapters.HTTPAdapter object at 0x1212b3ef0>)]), 'a': 'hello'}
*****
# 数据类型
a = set()
print(a.__dict__)
------
AttributeError: 'set' object has no attribute '__dict__'
II、魔法方法
- 1、既然都有__setattr__这个用法了,在定义类的时候,肯定也是可以制定的
- 2、重写了
__setattr__
方法之后,添加一个新的属性的时候,会调用这个方法 - 3、定制
__setattr__
方法的时候,他传入的值不能直接使用,否则会陷入无限递归中
class Test:
"""测试类"""
@staticmethod
def name():
return "Donald"
def __setattr__(self, key, value):
print(f'key->{key}')
self.key = value
a = Test()
a.age = 10
-------------
key->key
· # 很多个
·
key->key
RecursionError: maximum recursion depth exceeded while calling a Python object
- 4、正确的写法是在实例属性的列表中植入,如:
self.__dict__[key] = value
class Test:
"""测试类"""
@staticmethod
def name():
return "Donald"
def __setattr__(self, key, value):
print(f'key->{key}')
self.__dict__[key] = value
a = Test()
a.age = 10
print(a.__dir__())
-----
key->age
['age', '__module__', '__doc__', 'name', '__setattr__', '__dict__', '__weakref__', '__repr__', '__hash__', '__str__', '__getattribute__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
- 5、但是感觉这个魔法方的用武之地少的可怜,基本上都不会重写这个魔法方法
综上所所述:getattr在日常开发中用到的最多,当属老大,hasattr紧随其后,setattr的地位感觉会被property冲击
今天的文章Python的attr三兄弟(getattr、hasattr、setatter)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/28773.html