Does python have a shorthand to check if an object has an attribute?
背景是我从JSONAPI获取数据,其中有许多字段是可选的,我需要数据库中的大部分字段。当某个特定字段不可用时,我希望将一个空字符串(""写入数据库。
目前我一直在做:
1 2 3 4
| if jsonobject.what_i_look_for:
dbstring = jsonobject.what_i_look_for
else:
dbstring ="" |
然后将dbstring插入数据库。不过,我现在得到了更多的这些字段,我想要一个更干净的代码,而不是一个包含大约80%if语句的函数。
我已经找到了如果速记和这个速记来检查变量是否为空,但两者似乎都不能直接作为字符串工作。我在交互式python 3.5.2 shell中使用print()测试了这一点:
1 2 3 4 5 6 7 8 9
| >>> print(testvar or"")
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
NameError: name 'testvar' is not defined
>>> print(testvar if testvar else"")
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
NameError: name 'testvar' is not defined |
这:echo (isset($testvar) ? $testvar :"");是我所寻找的PHP等价物。
编辑:因为它似乎是相关的:我试图处理的对象来自于Telegram的JSONAPI。我使用python-telegram-bot作为库,这是一个示例对象。
- jsonobject.what_i_look_for是属性,不是变量。你的问题是关于变量还是关于属性?另外,if jsonobject.what_i_look_for:检查what_i_look_for_attribute是否设置为真实值;它不检查该属性是否存在。那么,你的问题到底是什么?
- python中不存在变量。有分配对象的名称。
- hasattr可能是你想要的,尽管最好是请求宽恕而不是允许。
- @阿兰菲Python有什么不同吗?我试过两种方法,结果完全一样,所以我觉得没关系。如果是这样,我将查看JSON对象是否包含属性(也可以是嵌套对象)。如果我需要改变我的问题,请告诉我。
- 是的,属性和变量是不同的。
- @五彩纸屑:什么是jsonobject。你自己的班级?图书馆的课程?字典?
- 如果你在寻找一个对象的属性,那么你可以使用hasattr(obj, name)来查看它是否存在,或者getattr(obj,name,default)`来获取这个属性是否存在,或者如果不存在的话返回默认值。但是如果你发现你自己对你的大多数属性都使用hasattr或getattr,这通常意味着你不想要一个obje。CT首先充满了属性,不过是一本字典。(请注意,stdlib json模块使用字典。)
- 我已经编辑了我的问题。
- @蓝色——准确地说,它是python电报bot.readthedocs.io/en/stable/telegrape.chat.h&zwnj;&8203;tml这个(和类似的)对象来自python电报bot。
- @Abarnert我并没有真正控制我得到的对象,我只是使用python-telegram-bot处理来自电报的JSONAPI的不同对象。
- @彼得伍德介意留下一个完整的答案吗?我需要的正是hasattr或getattr,它也可以作为速记。
pythonic方法是寻找NameError异常,当变量未定义时会引发异常,名称未绑定到任何要精确的对象。
例如:
1 2 3 4 5 6
| try:
foobar
except NameError:
# Do stuffs
print('foobar is not defined')
raise # raise the original exception again, if you want |
名称位于命名空间中,例如本地名称位于locals()命名空间(dict命名空间),全局名称位于globals()命名空间(dict命名空间)。您可以定义一个函数,将名称字符串和命名空间作为参数来检查是否存在,这里有一个提示,将命名空间作为dict传递,并捕获KeyError:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| In [1213]: def is_defined(name, namespace):
...: try:
...: namespace[name]
...: except KeyError:
...: return False
...: return True
...:
In [1214]: is_defined('spamegg', globals())
Out[1214]: False
In [1215]: spamegg = 10
In [1216]: is_defined('spamegg', globals())
Out[1216]: True |
另一方面,如果要获取对象的属性字符串的值,则可以使用getattr:
例如,以下两个是等效的:
1 2
| obj.foobar
getattr(obj, 'foobar') |
甚至可以在缺少对象属性时添加默认值:
1
| getattr(obj, 'foobar', 'spamegg') |
以上将输出值obj.foobar,如果缺少foobar,将输出spamegg。
您可能还对返回True/False进行属性存在性检查的hasattr感兴趣,而不需要手动处理AttributeError。
- 有没有一种方法可以为它编写函数或其他东西?我的目标是得到一个简洁的代码,对于我需要检查的每个变量都有一个try块并不能完全实现这一点。
- @五彩纸屑名称驻留在命名空间中,例如本地名称驻留在locals()命名空间中,全局名称驻留在globals()命名空间中。可以定义一个函数,该函数将命名空间作为参数来检查是否存在。
- 对于我来说,except NameError是相当重要的代码味道,除非你有一些相当神秘的元编程黑色魔法,也许。在任何情况下,阅读操作,我都不清楚这是否是他们需要的,因为他们谈论的是对象的属性。
- @五彩纸屑为什么你发现自己处于一种不知道名字是否在范围内的情况下?这似乎与您的问题一点关系都没有,问题是关于对象的属性,而不是变量是否被定义……
- @我已经编辑了我的作品,我想我一开始是错的。我添加了一个我正在处理的对象的示例。
- @希梅尔,这是一个很好的答案,但我需要的正是江户十一〔四〕。
- @五彩纸屑不用担心。在getattr上也增加了一些注释。
- 非常感谢,非常感谢。