Home > Back-end >  Equivalent implementation using f-strings and eval
Equivalent implementation using f-strings and eval

Time:06-03

x = type.__dict__
x is x

gives,

True

but,

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

gives,

SyntaxError: invalid syntax

even,

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

gives,

SyntaxError: invalid syntax

how to get True as output using eval and f-strings?

CodePudding user response:

When using eval you are executing exactly what you wrote in the string. By formatting with the curly brakets you are inserting in the string the value of "x", or at least whatever is returned by the "__str__" method of x.

print(f"{x}")

gives

{'__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>}

Meaning that's what you are trying to execute, which is indeed invalid syntax.

You should instead do:

eval("x is x")

CodePudding user response:

Works for me:

>>> 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

This works just fine with dicts.

However, calling str.__dict__ returns something completely different than you'd probably expect:

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

This "dict-representation" is actually a MappingProxy as you can verify with type(str.__dict__) and cannot exactly be re-interpreted by eval() as <built-in method __new__... is obviously a syntax error, when used without quotes. You can easily verify this by pasting this into a Python interpreter:

>>> {"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

What you're trying to do requires not only type (whatever this might be at runtime) to have a dict-representation, but also every member to have one - recursively! This is hard to assume in a general case.

I'm convinced what you're trying to achieve can be done using a different way - if you want elaborate your task at hand, there might be a more suitable way.

If you insist on the eval() way, take a look at repr() and eval(), as generally, repr tries to produce a string, which can be fed into eval to produce the very same object again. However, this is possible only, if the object implements repr to do exactly that - which is not guaranteed. There might be objects which cannot be serialized that way.

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

CodePudding user response:

To get the same as x is x through eval you need the name of the variable as a string "x" instead of the variable itself. How to get it is answered here: Getting the name of a variable as a string

Here is a solution for your case:

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

eval(f'{x_name} {operator} {x_name}')

Resulting in:

> True
  • Related