I am a newbie to ASTs as I come from a Statistics background. As per my observation, Python is unable to detect an if statement for the following code -
import ast
from pprint import pprint
tree = ast.parse("""
def add(a, b):
return a + b
def subr(a,b):
if 2>3:
print("true")
else:
print("false")
return 0
""")
for node in ast.iter_child_nodes(tree):
print(isinstance(node, ast.If))
However, if there is no function, it can detect the if statement -
import ast
from pprint import pprint
tree = ast.parse("""
if 2>3:
print("true")
else:
print("false")
""")
for node in ast.iter_child_nodes(tree):
print(isinstance(node, ast.If))
Could someone please tell me what is the problem with my former code block?
#Mathias R. Jessen is correct. iter_child_nodes() can only iterate through immediate child nodes. To iterate through the entire code, one should use ast.walk()
Related
I would like to import one python file into another and then compile the main file. How can I do this?
MWE: Suppose I would like to calculate factorial of a positive integer. It can be done successfully by the following way:
n=5
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
But I would like to create a secondary file say "auxfile.py" containing:
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
And another main file say "main.py" containing:
print "Required factorial is given below:"
for n in range(30):
import auxfile.py
How can I do this?
Note: I know defining a function the whole process can be done in a single file. But I have to do a large program where I would like to apply this process.
Simple, just use the import method. To make your life easier simply copy the .py file you would like to import to the same folder that the file you want to import the other code file into is in.
E.g if you wanted to import happy.py to sad.py simply do:
import happy
This would give the following traceback (look at example below):
Hello
Although, this will instantly run everything outside of any def loops in the .py file. Therefore, if you wanted to run a single def loop in the file, then use the following code:
Example contents of happy.py:
print("Hello")
def okay():
print("okay")
If you did:
happy.okay()
This would give you the following traceback:
Hello
okay
TIP FOR YOUR CODE IN MAIN.PY:
You did:
print "Required factorial is given below:"
whereas you forgot the brackets. You should use: print("Required factorial is given below:") This will avoid future errors!
Hope this helps!
you can do it like this:
auxfile.py
def factorial(n):
fact = 1
if n < 0:
print("Sorry, factorial does not exist for negative numbers")
elif n == 0:
print("The factorial of 0 is 1")
else:
for i in range(1,n + 1):
fact = fact*i
print "%d!=%d"%(n,fact)
in your main.py :
from auxfile import factorial
print "Required factorial is given below:"
for n in range(30):
factorial(n)
If you're trying to avoid using a function--maybe you could wrap your entire code in the for loop? If it is not as simple as a for-loop, maybe you could copy your main code into the other file above it.
For example:
Before:
file1: "Your main code that wants to call the code below"
file2: "Your code that is too cumbersome to convert to a function"
After:
file1:
"Your main code that wants to call the code below"
for n in range(30):
"Your code that is too cumbersome to convert to a function"
There's still quite an ugly solution, which is to use the exec built-in function.
First of all, you read the code from your file:
with open("auxiliary.py", 'r') as f:
content = f.readlines()
Then you filter out the lines you don't want, so that content is a string containing your Python code, that is:
# The following evaluates to True
content == 'fact = 1\nif n < 0:\n print("Sorry, factorial does not exist for negative numbers")\nelif n == 0:\n print("The factorial of 0 is 1")\nelse:\n for i in range(1,n + 1):\n fact = fact*i\n print "%d!=%d"%(n,fact)'
Then you can just call the exec function, which will act as if the lines were included in lieu of the call of the function:
exec content # Or exec(content), both seems to work in Python 2.7
See here for a further explanation.
Note that you will have access to fact and every other variables, just as if you had written these lines in your main file.
Be aware that this might get dangerous: if you don't formally identify which lines to execute (like, put a comment as an identifier, or if the auxiliary file never changes), you may end up running some code from your auxiliary file you dont want to.
I wrote a function to traverseMountain(altitude, stepsleft, substring) as helper function to part of a solution to one of the hackerrank problems. I consider it better practice to test functions as I write them, and this is where I am encountering my problem.
#!/bin/python3
import math
import os
import random
import re
import sys
# Complete the countingValleys function below.
def countingValleys(n, s):
altitude = 0
mountiansCount = 0
valleysCount = 0
def tailRecurseSolution(stepsleft, substring):
head, tail = substring[0], substring[1:]
if (head == 'U'):
mountiansCount+=1
traverseMountain(n-1, tail)
if (head == 'D'):
traverseValley(altitude+1, n-1, tail)
# return valleysCount
def traverseMountain(altitude, stepsleft, substring):
head, tail = substring[0], substring[1:]
if (head=="D"):
altitude-=1
if (head=="U"):
altitude+=1
stepsleft-=1
if (altitude<=0 or stepsleft<=0 or (not tail)):
x = stepsleft
return x
elif (altitude>0 and stepsleft>0 and tail):
traverseMountain(altitude, stepsleft,tail)
#def traverseValley(alt, stepsleft, substring):
# return x
if __name__ == '__main__':
altitude = 0
stepsleft = 99
path = "UUUDUDDD"
print(traverseMountain(altitude, stepsleft, path))
You can ignore the countingValleys function as its imcomplete and not being called.
What I was expecting to happen was for the function traverseMountian to meet the if conditional, and would step into the block upon the last recursive call (when altitude variable is 0 or the tail is the empty string) and then exit the function and return the value of the stepsLeft variable.
What I am witnessing is that my debugger steps inside of that if statement, but immediately jumps to inside the elif statement (I do not understand why it would do that) and the variables I receive are reset?
I wanted to make a post here in case it's intended behaviour of the code
I've spent a lot of time today just trying to figure out why Python does not terminate the function after the return statement. I've played out with the conditionals, the placing of the return statement etc. but without success.
You're returning x but in your recursion call you're not doing anything with the return value.
You might want return traverseMountain(altitude, stepsleft,tail) as your last line in traverseMountain?
I'm not sure what's going on with this problem.
I place the exact same code in a jupyter notebook and everything runs fine. But when I place the code in Hackerrank it does not return any output.
Does anyone spot the error here?
Sample:
6 4
give me one grand today night
give one grand today
#!/bin/python3
import math
import os
import random
import re
import sys
from collections import Counter
# Complete the checkMagazine function below.
def checkMagazine(magazine, note):
ds = Counter(magazine)
for m in note:
ds[m] = ds[m] - 1
if ds[m] < 0 or ds[m] is None: return 'No'
return 'Yes'
if __name__ == '__main__':
mn = input().split()
m = int(mn[0])
n = int(mn[1])
magazine = input().rstrip().split()
note = input().rstrip().split()
checkMagazine(magazine, note)
This code returns but doesn't print the output to stdout that the HR code runner is looking for. Try print(checkMagazine(magazine, note)).
In general, HR is a bit fussy about IO. Data will be read through stdin and will be printed to stdout, often in bizarre formats like "Yes" or "Impossible!" for a function that would normally return a boolean.
I want to make a coin toss / dice roll in python but i cannot figure out how to define / change a variable inside an if statement.
import random
def roll(number):
if(number==1):
{print("Take a moment to think that through")}
if(number==2):
{b=random.randint(0,1)
if(b=0):
{ba=1}
else:
{bb=1}
}
the part, {b=random.randint(0,1)} the = is highlighted red and marked as a syntax error. I also tried this:
import random
b=0
def roll(number):
if(number==1):
{print("Take a moment to think that through")}
if(number==2):
{b+=random.randint(0,1)
if(b=0):
{ba=1}
else:
{bb=1}
}
that gives the same error, and the = is highlighted, not the +
and before you ask, the function roll(number) is called in the shell. the shell is my interface.
import random
def roll(number):
if number==1:
print("Take a moment to think that through")
if number==2:
b=random.randint(0,1)
if b==0:
ba=1
else:
bb=1
Python doesn't use curly braces, you should write your codes like this.Also you have to return something in your function.This is how you can use your function/variables with another methods.
import random
def roll(number):
if number==1:
my_string="Take a moment to think that through"
return my_string
if number==2:
b=random.randint(0,1)
if b==0:
ba=1
else:
bb=1
return ba,bb
Something like this, I don't know your whole code so.
You should also think about what should happen if someone enters, for example, roll(15).
import random
def roll(number):
if number==1:
print("Take a moment to think that through")
elif number==2:
b=random.randint(0,1)
if b==0:
ba=1
else:
bb=1
else:
print("What should happen in this case?")
Also, #grrr: if b==0
Why am i getting an "invalid syntax" when i run below code. Python 2.7
from string import *
def countSubStringMatch(target,key):
counter=0
fsi=0 #fsi=find string index
while fsi<len(target):
fsi=dna.find(key,fsi)
if fsi!=-1:
counter+=1
else:
counter=0
fsi=fsi+1
fsi=fsi+1
#print '%s is %d times in the target string' %(key,counter)
def countSubStringMatch("atgacatgcacaagtatgcat","atgc")
In the line:
def countSubStringMatch("atgacatgcacaagtatgcat","atgc")
You should remove the def. def is used when defining a function, not when calling it.
for string count you could just do:
target = "atgacatgcacaagtatgcat"
s = 'atgc'
print '%s is %d times in the target string' % (s, target.count(s))
Other things wrong with your code:
You don't use and don't need anything in the string module. Don't import from it.
Don't do from somemodule import * unless you have a very good reason for it.
Your code rather slowly and pointlessly struggles on after the first time that find returns -1 ... your loop should include
if fsi == -1: return counter
so that you return immediately with the correct count.
Be consistent: you use counter += 1 but fsi = fsi + 1
... which reminds me: find 'PEP 8' (style guide) at www.python.org, and read it -- your space bar must be feeling unloved ;-)
HTH
John