python: how to get the source from a code object? [duplicate] - python

This question already has answers here:
What tools or libraries are there for decompiling python and exploring bytecode? [closed]
(6 answers)
Closed 9 years ago.
let's suppose we have a python string(not a file,a string,no files)
TheString = "k=abs(x)+y"
ok? Now we compile the string into a piece of python bytecode
Binary = compile( TheString , "<string>" , "exec" )
now the problem: how can i get from Binary , supposing i don't know TheString , a string that represents the original string object?
shortly: what is the function that is opposite to compile() ?

Without the source code, you can only approximate the code. You can disassemble the compiled bytecode with the dis module, then reconstruct the source code as an approximation:
>>> import dis
>>> TheString = "k=abs(x)+y"
>>> Binary = compile( TheString , "<string>" , "exec" )
>>> dis.dis(Binary)
1 0 LOAD_NAME 0 (abs)
3 LOAD_NAME 1 (x)
6 CALL_FUNCTION 1
9 LOAD_NAME 2 (y)
12 BINARY_ADD
13 STORE_NAME 3 (k)
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
From the disassembly we can see there was 1 line, where a function named abs() is being called with one argument named x. The result is added to another name y, and the result is stored in k.
Projects like uncompile6 (building on top of the work of many others) do just that; decompile the python bytecode and reconstruct Python code from that.

Related

Variable inside python format specifier [duplicate]

This question already has an answer here:
How to pad numbers with variable substitution for padding width in format or f string? [duplicate]
(1 answer)
Closed 7 months ago.
I am wondering whether I can add a variable inside the f string to specify the width of item to be printed.
For example:
print("{:>5}".format("cat"))
In the example how can I replace 5 with a variable that can change at runtime.
inside the f string
Be careful using the term "f string" -- you're talking about a format string whereas an f-string is a feature of the latest releases of Python and something different, but related:
animal = 'cat'
pad = 5
print(f"{animal:>{pad}}")
Otherwise, if you just want a format string without the f-string, then #JohnnyMopp's comment (+1) shows the correct syntax.
Here is how:
a = 5
print("{:>"f"{a}""}".format("cat"))
Output:
cat
You can also do that using str.rjust():
a = 5
print("cat".rjust(a))
Output:
cat

Style for continued multi-line f-strings [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Do any popular Python style guides express a preference between:
x = (f'One plus one is '
f'equal to {1+1}')
and:
x = ('One plus one is '
f'equal to {1+1}')
Does it make sense to omit the f prefix for lines that don't involve interpolation? Should it be included for consistency?
If you look at the generated byte code for each of those two options, you will see that this both results in the same set of operations:
>>> dis.dis("""f'One plus one is ' f'equal to {1+1}'""")
1 0 LOAD_CONST 0 ('One plus one is equal to ')
2 LOAD_CONST 1 (2)
4 FORMAT_VALUE 0
6 BUILD_STRING 2
8 RETURN_VALUE
>>> dis.dis("""'One plus one is ' f'equal to {1+1}'""")
1 0 LOAD_CONST 0 ('One plus one is equal to ')
2 LOAD_CONST 1 (2)
4 FORMAT_VALUE 0
6 BUILD_STRING 2
8 RETURN_VALUE
So for Python, this both does exactly the same thing: The string is being concatenated at compile-time, and the whole string is being evaluated as a format string.
Note though that as per the PEP, f-strings are actually concatenated at run-time, to make sure that every format expression is evaluated independently:
Adjacent f-strings and regular strings are concatenated. Regular strings are concatenated at compile time, and f-strings are concatenated at run time.
That is why the following example will generate two FORMAT_VALUE opcodes:
>>> dis.dis("""f'{2+2}' f'{3+3}'""")
1 0 LOAD_CONST 0 (4)
2 FORMAT_VALUE 0
4 LOAD_CONST 1 (6)
6 FORMAT_VALUE 0
8 BUILD_STRING 2
10 RETURN_VALUE
This will not have an effect for f-strings that don’t actually contain any format placeholders though. Those will still be concatenated at compile-time:
>>> dis.dis("""f'foo' f'bar'""")
1 0 LOAD_CONST 0 ('foobar')
2 RETURN_VALUE
So you can just include the f prefix for constant strings anyway and when they don’t contain a format expression, they won’t end up being handled as format strings.
So in your particular case, since there is no functional difference and both options are compiled to the same thing, that leaves this as a pure style choice which everyone has to answer for themselves.
If you are looking at existing style guides, chances are that they are not covering f-strings yet. But then, you could use the same guideline as for raw strings, although I personally don’t expect style guides to really cover that area much. Just choose what looks best, is readable, and what makes most sense to you. After all, continued strings are not really that common (and you are more likely to have triple-quotes for longer strings).

Behaviour of "is" is different for primitives in python [duplicate]

This question already has an answer here:
What's with the integer cache maintained by the interpreter?
(1 answer)
Closed 6 years ago.
is in Python tests if 2 references point to the same object.
Numbers between -5 and 256 are cached internally so:
a = 10
b = 10
a is b # Results in True
How does this explain something like:
20000 is 20000 # Results in True
Both numbers are above 256.
Should not the 2 integers be 2 distinct objects?
The Python interpreter sees you are re-using a immutable object, so it doesn't bother to create two:
>>> import dis
>>> dis.dis(compile('20000 is 20000', '', 'exec'))
1 0 LOAD_CONST 0 (20000)
3 LOAD_CONST 0 (20000)
6 COMPARE_OP 8 (is)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Note the two LOAD_CONST opcodes, they both load the constant at index 0:
>>> compile('20000 is 20000', '', 'exec').co_consts
(20000, None)
In the interactive interpreter Python is limited to having to compile each (simple or compound) statement you enter separately, so it can't reuse these constants across different statements.
But within a function object it certainly would only create one such integer object, even if you used the same int literal more than once. The same applies to any code run at the module level (so outside of functions or class definitions); those all end up in the same code object constants too.
Python stores objects in memory to make things more efficient. It only needs to assign one block of memory to 20000, and so both references point to the same block of memory, resulting in True.

increment operator ++i does not cause an error in python [duplicate]

This question already has answers here:
Behaviour of increment and decrement operators in Python
(11 answers)
Closed 8 years ago.
Since the increment operator ++ is not supported in python, why doesn't it cause an error when prefixing a variable. Example:
i = 3
++i
prints 3 on the interactive console. Why is that?
Take a look - it's just a sign:
>>> i = 3
>>> +i
3
>>> ++i
3
>>> +++i
3
>>> -i
-3
>>> --i
3
>>> ---i
-3
Python treats ++i as +(+i), that would compile fine, and print the same value as of i.

Is 01208 has a special meaning in python or just a bug of python2.6.2? [duplicate]

This question already has answers here:
Python: Invalid Token
(3 answers)
Closed 9 years ago.
within python runtime environment, try the following:
>> *type(01207)*
you'll get:
<type 'int'>
then try with:
>> *type(01208)*
you will get:
File "<stdin>", line 1
type(01208)
^
No it isn't a bug, by prefixing the number with 0 you are using octal and 8 is not a valid digit in base 8.
>>> 07
7
>>> 08
SyntaxError: invalid token
>>> 010
8
Python 3 uses a 0o prefix (only - you can do both in 2.7) instead to remove this ambiguity.

Categories