使用f-string和eval的等价实现


x = type.__dict__
x is x

,

True

,

x = type.__dict__
operator = 'is'
eval(f'{x} {operator} {x}')

,

SyntaxError: invalid syntax

,

operator = 'is'
eval(f'{x!r} {operator} {x!r}')

,

SyntaxError: invalid syntax

如何获得True作为输出使用eval和f字符串?

使用eval时,您执行的正是您在字符串中所写的内容。通过使用花括号格式化,您将在字符串中插入"x"的值,或者至少是"返回的任何值。__str__";x.方法

print(f"{x}")

{'__repr__': <slot wrapper '__repr__' of 'type' objects>, '__call__': <slot wrapper '__call__' of 'type' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'type' objects>, '__setattr__': <slot wrapper '__setattr__' of 'type' objects>, '__delattr__': <slot wrapper '__delattr__' of 'type' objects>, '__init__': <slot wrapper '__init__' of 'type' objects>, '__new__': <built-in method __new__ of type object at 0x908780>, 'mro': <method 'mro' of 'type' objects>, '__subclasses__': <method '__subclasses__' of 'type' objects>, '__prepare__': <method '__prepare__' of 'type' objects>, '__instancecheck__': <method '__instancecheck__' of 'type' objects>, '__subclasscheck__': <method '__subclasscheck__' of 'type' objects>, '__dir__': <method '__dir__' of 'type' objects>, '__sizeof__': <method '__sizeof__' of 'type' objects>, '__basicsize__': <member '__basicsize__' of 'type' objects>, '__itemsize__': <member '__itemsize__' of 'type' objects>, '__flags__': <member '__flags__' of 'type' objects>, '__weakrefoffset__': <member '__weakrefoffset__' of 'type' objects>, '__base__': <member '__base__' of 'type' objects>, '__dictoffset__': <member '__dictoffset__' of 'type' objects>, '__mro__': <member '__mro__' of 'type' objects>, '__name__': <attribute '__name__' of 'type' objects>, '__qualname__': <attribute '__qualname__' of 'type' objects>, '__bases__': <attribute '__bases__' of 'type' objects>, '__module__': <attribute '__module__' of 'type' objects>, '__abstractmethods__': <attribute '__abstractmethods__' of 'type' objects>, '__dict__': <attribute '__dict__' of 'type' objects>, '__doc__': <attribute '__doc__' of 'type' objects>, '__text_signature__': <attribute '__text_signature__' of 'type' objects>}

意味着你正在尝试执行的内容,这确实是无效的语法。

你应该这样做:

eval("x is x")

适合我:

>>> d = {"a":42}
{'a': 42}
>>> print(f"{d} is {d}")
{'a': 42} is {'a': 42}
>>> {'a': 42} is {'a': 42}
False
>>> eval(f"{d} is {d}")
False

这对于字典来说很好。

然而,调用str.__dict__返回的结果可能与您期望的完全不同:

>>> str.__dict__
mappingproxy({
'__new__': <built-in method __new__ of type object at 0x00007FFC55D1AC60>,
'__repr__': <slot wrapper '__repr__' of 'str' objects>,
--- snip for readability ---

这"dict-representation"实际上是MappingProxy,因为您可以用type(str.__dict__)进行验证,并且不能完全由eval()重新解释,因为<built-in method __new__...显然是语法错误,当没有引号使用时。您可以通过将其粘贴到Python解释器中来轻松验证这一点:

>>> {"myKey": <built-in method __new__ of type object at 0x00007FFC55D1AC60>}
File "<stdin>", line 1
{"myKey": <built-in method __new__ of type object at 0x00007FFC55D1AC60>}
^
SyntaxError: invalid syntax

你要做的不仅需要type(无论在运行时是什么)有一个字典表示,而且每个成员都有一个——递归地!这在一般情况下很难假设。

我相信你想要达到的目的可以用另一种方法来完成——如果你想详细说明手头的任务,可能有更合适的方法。

如果你坚持eval()的方式,看看repr()eval(),一般来说,repr试图产生一个字符串,可以输入eval来再次产生相同的对象。然而,这是可能的,如果对象实现了repr来做这个——这是不能保证的。可能存在不能用这种方式序列化的对象。

myDict = {"myKey": "myVal"}
myDict == eval(repr(myDict))
# Output: True

要通过eval获得与x is x相同的内容,您需要名称变量的字符串"x"而不是变量本身。如何获得它的答案在这里:获取一个变量的名称作为字符串

这是你的情况的解决方案:

x = type.__dict__
operator = 'is'
x_name = f'{x=}'.split('=')[0]
eval(f'{x_name} {operator} {x_name}')

导致:

> True

最新更新