3

Reading the definition of the bin() function in Python, the officicial documentation (3.4) says, that the binary string returned by bin() is a valid Python expression.

This has made me wonder: can a function return an invalid Python expression ? And what exactly is the definition of an valid/invalid Python expression ?

Shuzheng
  • 11,288
  • 20
  • 88
  • 186
  • 1
    What it means is that the contents of the string are valid python code. If you return a string from a function with the contents `"forty two"`, that is not a valid python expression. If you return a string with the contents `"0b101010"`, then that is a valid python expression, because you can write `x=0b101010` in python and it will run. – khelwood Apr 08 '15 at 18:24

5 Answers5

4

Functions do not return expressions. They return values. What the documentation says is that the value returned by bin is a string that represents a valid python expression. In fact the returned value represents a binary literal.

You can check whether a string is a valid expression by evaluating it using eval:

eval(text)

Warning: never call eval on contents that you don't control (e.g. user provided strings) and avoid using it in general. It's a security hazard.

Note: There's also a ast.literal_eval that is safer (i.e. when executed it will not anything bad so you can use it on user-provded text etc.) but only works for literal expressions (i.e. expressions without variables/method or function calls. Only literals and operators)

A better way to check it is by parsing it using the ast.parse function:

ast.parse(text, mode='eval')

The mode='eval' specifies to parse the content as an expression.

This is better because it avoids to execute the expression. If the function raises an exception is because the syntax isn't valid. If it succeeds then the text represents a valid python expression:

>>> import ast
>>> ast.parse('1+', mode='eval')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    1+
     ^
SyntaxError: unexpected EOF while parsing
>>> ast.parse('1+1', mode='eval')
<_ast.Expression object at 0x7f10376c4e10>

So you could use something like the following:

def is_valid_expr(expr):
    try:
        ast.parse(expr, mode='eval')
    except SyntaxError:
        return False
    else:
        return True

as in:

if is_valid_expr(some_text):
    print("It's valid!")
else:
    print("It's invalid!")

Formally a valid expression is defined by the python grammar (see the expr non terminal). The ast.parse function uses that grammar to parse its input.


Note: using ast.parse you can check whether a string is valid python statement or generic code. Just use mode='single' for a single statement and mode='exec' for generic code.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • So a string in itself is a valid Python expression, since it is a value. But in this case, the contents of the string represent a valid Python expression ? – Shuzheng Apr 09 '15 at 08:30
  • @NicolasLykkeIversen A string is **not** an expression. A string is a value, period. You are confusing the *syntax* of a program with its *semantic*. The term expression *only* refers to the *syntax*. However when a function is executed it *only* handles *values*, not expressions. It so happens the content of a string value can represent a valid *syntactic* term. You could define a graphical representation for python programs, in which case images would be expressions and things that return image values could return image values whose contents are valid expressions. – Bakuriu Apr 09 '15 at 10:44
  • What exactly is the definition of an expression then ? I've read that an expression is anything that represents a value in Python, so a value is an expression...". Thank you for your help. – Shuzheng Apr 09 '15 at 12:43
  • @NicolasLykkeIversen Do you understand when I say the term *syntax*? The word expression refers to a *syntactic* term in a given language. A syntactic term is defined by a *grammar* (see the link I've put in the answer). If you cannot understand this you should read something about *formal languages* and *parsing*. Then you'll probably have a clearer understand of the distinction between expressions and values. – Bakuriu Apr 09 '15 at 13:09
  • Thank you, I will look into this. Could you recommend a good book ? – Shuzheng Apr 09 '15 at 14:05
1

It means the result can be evaluated either through eval or if entered directly. For example:

>> bin(20)
'0b10100'

>>> 0b10100
20

>>> eval('0b10100')
20

In general a valid expression in programming languages is something that returns a result, without having syntax errors. In python eval accepts a string containing a expression according to the definition:

eval(expression[, globals[, locals]])

If the expression is invalid, a SyntaxError is thrown:

>>> eval('1+')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    1+
SyntaxError: unexpected EOF while parsing

We have to pay attention, that some expressions may have illegal values but are still considered valid, like 1 / 0:

>>> eval('1/0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
JuniorCompressor
  • 19,631
  • 4
  • 30
  • 57
1

A "valid expression" is a string that can be eval()'d -- or ast.literal_eval() (for literals).


>>> bin(20)
'0b10100'

0b10100 is a valid literal:

>>> ast.literal_eval(bin(20))
20
>>> ast.literal_eval(bin(20)) == 20
True

OTOH, b10100 isn't:

>>> ast.literal_eval("b10100") == 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sylvain/local/lib/python3.3/ast.py", line 86, in literal_eval
    return _convert(node_or_string)
  File "/home/sylvain/local/lib/python3.3/ast.py", line 85, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x7fdcefd9b9d0>
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • Thank you. How do you know this ? Googling "What is a valid Python expression" doesn't bring much useful ? – Shuzheng Apr 08 '15 at 18:28
0

here you see in this example:

>>> bin(4)
'0b100'
>>>

The binary is prefixed with 0b that represent a valid python Expression for Binary Number in python

Hackaholic
  • 19,069
  • 5
  • 54
  • 72
0

For more info on what an expression is see What is an expression in Python? but it just mean's its a valid string representation of a binary number in python.

Community
  • 1
  • 1
joe.dawley
  • 466
  • 4
  • 14