python2和python3中hasattr的区别
2021-10-12 00:39
分析hasattr在python2/python3下遇到的不同行为的问题
先说结论:
python2和python3的hasattr实现,实际是调用getattr,然后判断是否会抛出异常,如果抛出异常,则判定为没有指定的属性返回false,否则返回true。但是python2会捕获所有的异常,而python3仅捕获PyExc_AttributeError异常,其他异常会继续向上抛,导致上层逻辑收到异常。
相关依据:
python2的hasattr文档描述看这里,代码实现看这里
python3的hasattr文档描述看这里,代码实现看这里
代码例子:
class Test(object):
a = "this is a"
def __init__(self):
self.b = "this is b"
def c(self):
print("this is c")
x=1/0
@property
def d(self):
print("this is d")
x=1/0
test = Test()
print("a" in dir(test))
print("b" in dir(test))
print("c" in dir(test))
print("e" in dir(test))
print("d" in dir(test))
python2输出
近期遇到一个python2和python3在处理flask逻辑的坑,代码如下,在路由中判断是否传入json数据。
import flask
...
@app.route(...)
def test():
...
print(hasattr(request, 'json'))
...
...
python2的表现:可以正常返回true/false
python3的表现,抛出如下异常:
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "api.py", line 1485, in test
print(hasattr(request, 'json'))
File "/usr/lib/python3.6/site-packages/werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 108, in json
return self.get_json()
File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 155, in get_json
rv = self.on_json_loading_failed(e)
File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 174, in on_json_loading_failed
raise BadRequest('Failed to decode JSON object: {0}'.format(e))
werkzeug.exceptions.BadRequest: 400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)