I'm going crazy with the following code which should be really easy but doesn't work :/
class Triangulo_String:
_string = ''
_iteraciones = 0
_string_a_repetir = ''
def __init__(self, string_a_repetir, iteraciones):
self._string_a_repetir = string_a_repetir
self._iteraciones = iteraciones
def concatenar(self):
for i in range(0, self._iteraciones, 1):
self._string = self._string_a_repetir + self._string + '\n'
I'm initializing _iteraciones to 3 and _string_a_repetir to '*'
And the output is just:
***
When I'm expecting:
*
**
***
I've debugged it and when doing the concatenating it just concatenates the self._string_a_repetir, not the _string nor the line break.
Such an easy thing is driving me crazy ._.
The relevant bit is in this part:
for i in range(0, self._iteraciones, 1):
self._string = self._string_a_repetir + self._string + '\n'
Let’s go through the iterations one by one:
# Initially
_string = ''
_string_a_repetir = '*'
_iteraciones = 3
# i = 0
_string = _string_a_repetir + _string + '\n'
= '*' + '' + '\n'
= '*\n'
# i = 1
_string = _string_a_repetir + _string + '\n'
= '*' + '*\n' + '\n'
= '**\n\n'
# i = 2
_string = _string_a_repetir + _string + '\n'
= '*' + '**\n\n' + '\n'
= '***\n\n\n'
As you can see, this is totally expected to happen, since you never repeat that character more than once per line. And you are also incorrectly concatenating the previous string with the new string (placing it in between the current line’s text and its line break).
What you are looking for is something like this:
for i in range(0, self._iteraciones, 1):
self._string = self._string + (self._string_a_repetir * (i + 1)) + '\n'
The string * number works to repeat the string for number times.
As a general note, you should not use those class members that way:
class Triangulo_String:
_string = ''
_iteraciones = 0
_string_a_repetir = ''
This will create those members as class variables, which are shared across all its instances. This is not directly a problem if you never change the class members but it could cause confusion later. You should instead initialize all instance attributes inside the __init__:
class Triangulo_String:
def __init__(self, string_a_repetir, iteraciones):
self._string = ''
self._string_a_repetir = string_a_repetir
self._iteraciones = iteraciones
Related
I'm trying to use a lambda to check if an object (self)'s attribute problematic_object is None. If it is, it should return a "" (an empty string), and if not, str(self.problematic_object). I've tried doing it in 3 ways:
1:
def __str__(self):
return "string1" + str(self.object) + "\n" + "string2" + self.another_object + "\n" + "string3" + exec(lambda self: str(self.problematic_object) if self.problematic_object!=None else "")
2:
def __str__(self):
return "string1" + str(self.object) + "\n" + "string2" + self.another_object + "\n" + "string3" + (lambda self: str(self.problematic_object) if self.problematic_object!=None else "")
3:
def __str__(self):
return "string1" + str(self.object) + "\n" + "string2" + self.another_object + "\n" + "string3" + lambda self: str(self.problematic_object) if self.problematic_object!=None else ""
I get this error in all the cases:
SyntaxError: invalid syntax
I know that this can be done using a normal if-else, but is there any way I can do it using a lambda? This is my first time using a lambda and this kind of an if-else. What is the mistake I'm making? Can a lambda be used like this?
If self.problematic_object is possibly None, and in that case you just want an empty string, simply use f-strings to add it to your overall string. No need for any boolean logic:
def __str__(self):
return f"string1{self.object}\nstring2{self.another_object}\nstring3{self.problematic_object}"
If self.problematic_object is None then nothing will be added to the end of the string. If it's not None then its value will be added.
In Python 3.6. What I'm trying to do is create a function that can accept any object and then generate a tree like contents.
Similar to a book:
1. Object
1.1 member: integer
1.2 member: list
2.1 list: element 1
2.2 list: element 2
1.3 member: string
My purpose is to use the numbers as a key for a technical readout, the number could also stand in for a more understandable ID number than id() generates. Because the objects I want to deal with are all types, I'd like the function to be recursive. Here is what I have so far:
def contents(a, n = 0, lim = 5, prefix=""):
index = 1
text = ""
j = None
if n < lim:
try:
for i in a.__dict__:
text = text + "\n" + ("\t" *(n)) + prefix + str(index) + ", " + str(i) + ": " + contents(a.__dict__[i], n = n + 1, prefix=str(n)+".") + ""
index += 1
except:
try:
for i, j in a.items():
text = text + "\n" + ("\t"*(n)) + prefix + str(index) + ", " + str(i) + ": " + contents(i, n = n + 1, prefix=str(n)+".") + ""
index += 1
except:
if isinstance(a, str):
text = text + "\n" + ("\t"*(n)) + prefix + str(index) + ", " + str(a) + " "
else:
try:
for i in a:
text = text + "\n" + ("\t"*(n)) + prefix + str(index) + ", " + str(i) + contents(i, n = n + 1, prefix=str(n)+".") + " "
index += 1
except:
text = text + "\n" + ("\t"*(n)) + prefix + str(index) + ", " + str(a) + " "
else:
text = text + "limit. \n"
return text
a is the object, n is the current number of recursion, lim is the recursion limit, prefix has to do with the object ID displayed.
Here's the testing object
class Aclass:
def __init__(self):
self.a = [12, 24]
self.b = 5
a = [Aclass(), 1, "2", 3, 4, Aclass(), {"c":"d","e":"f"}]
The problem I'm running into has to do with strange revursive behavior with lists, I already made an exception for strings, because the string would register as an iterable made up of iterables, which would recurse indefinitely if I hadn't put in a limit. Now simple lists of numbers like [1, 2, 3, 4] will often list the number twice as if it breaks down into a one item list [1] and then reports on the number inside: 1.
You should have a look at the pprint module, which is part of the standard distribution. It solves this problem already, and so might serve as a basis for your code. (I can easily see, for instance, adding numbers by subclassing the PrettyPrinter class.)
This code:
class Aclass:
def __init__(self):
self.a = [12, 24]
self.b = 5
a = [Aclass(), 1, "2", 3, 4, Aclass(), {"c":"d","e":"f"}]
import pprint
s = pprint.pformat(a, indent=4)
print(s)
Produces this output:
[ <__main__.Aclass object at 0x1060fb160>,
1,
'2',
3,
4,
<__main__.Aclass object at 0x1060fb198>,
{'c': 'd', 'e': 'f'}]
I'm having some formatting issues with my call to print function. For lack of knowledge of better ways to format, i've ended up with an issue. here is what it should look like
However the actual result of my print returns this.
def tupleMaker(inputString):
s1 = inputString.split()
# Adding the surname at the end of the string
s2 = [s1[len(s1) - 1]]
# Number of other names(no surname)
global noOfNames
noOfNames = len(s1) - 4
# Adding all the other names
for i in range(noOfNames):
s2.append((s1[i + 3]))
# Adding the Reg number
s2.append(s1[0])
# Adding the Degree scheme
s2.append(s1[2])
# Adding the year
s2.append("Year " + s1[1])
# Making it a tuple
t = ()
for i in range(len(s2)):
t = t + (s2[i],)
return t
def formatting(t):
s1 = ""
for i in range(len(t)):
s1 += t[i]
if (i == 0):
s1 += ", "
elif (i == len(t) - 4):
s1 += " "
else:
s1 += " "
#print(t[0] + ", ", end="")
#for i in range(noOfNames):
#print (t[i+1], end= " ")
#print(format(t[1+noOfNames], "<32s"))
#print(format(thenames, "<32d") + format(regNo, "<7d") + format(degScheme, ">6s") + format(year, ">1s")
print("")
print(s1)
I would recommend looking at using pythons built in string.format() function a small tutorial is located here: https://pyformat.info/
import sys
import string
import re
keywords = []
task = "*"
while task not in "ed":
task = raw_input("Encrypt or Decrypt: \nType ‘e’ to Encrypt\nType ‘d’ to Decrypt\n").lower()
keyword = "*"
keyphrase = "*"
while not(re.match('[a-z ]+$',keyword)):
keyword = raw_input("enter your first keyword:-").lower()
while not(re.match('[a-z ]+$',keyphrase)):
keyphrase = raw_input("enter a key phrase:-").lower()
loop = 0
repeated_keyword = ""
if len(keyword) < len(keyphrase):
while len(repeated_keyword) < len(keyphrase):
repeated_keyword = repeated_keyword + keyword[loop]
loop += 1
if loop >= len(keyword):
loop = 0
elif len(keyword) == len(keyphrase):
repeated_keyword = keyword
last_charecter_in_keyword = keyword[-1]
elif len(keyword) > len(keyphrase):
repeated_keyword = keyword
last_charecter_in_keyword = keyword[-1]
while len(repeated_keyword) > len(keyphrase):
repeated_keyword = repeated_keyword[:-1]
repeated_keyword_letter_positions = []
keyphrase_letter_positions = []
for character in repeated_keyword:
position_of_char_in_repeated_keyword = (string.ascii_lowercase + " ").find(character) +1
repeated_keyword_letter_positions.append(position_of_char_in_repeated_keyword)
for character in keyphrase:
position_of_char_in_keyphrase = (string.ascii_lowercase + " ").find(character)
keyphrase_letter_positions.append(position_of_char_in_keyphrase)
if task == "e":
final_positions_of_letters = [a + b for a, b in zip(keyphrase_letter_positions,repeated_keyword_letter_positions)]
elif task == "d":
final_positions_of_letters = [a - b for a, b in zip(keyphrase_letter_positions,repeated_keyword_letter_positions)]
new_letter = ""
final_cipher = []
loop = 0
alphabet = string.ascii_lowercase + " " + string.ascii_lowercase + " "
while loop < len(final_positions_of_letters):
new_letter =alphabet[final_positions_of_letters[loop]]
final_cipher = str(final_cipher) + str(new_letter)
loop += 1
print final_cipher
This is a encryption/ decryption programme in python 2.7. However at the end of the programme when the final_cipher list is printed to the shell a pair of [] brackets are printed prior to the contents of the list
You have some options here:
• Loop through the array, and print each element on the same row without delimiter.
• Use 'join' to join all the parts of the array in a single string. You can find more information about the join statement here.
Personally I do think 'join' is the best option here.
I guess you are trying to output a string. And you are making a mistake by setting the initial declaration to an empty list.
For fixing this just use :
final_cipher = "" instead of final_cipher = []
This should get you the output in string format.
Seeing:
final_cipher = []
loop = 0
alphabet = string.ascii_lowercase + " " + string.ascii_lowercase + " "
while loop < len(final_positions_of_letters):
new_letter =alphabet[final_positions_of_letters[loop]]
final_cipher = str(final_cipher) + str(new_letter)
loop += 1
print final_cipher
I see that you are working with final_cipher like a string, then you should initialize like:
final_cipher = ""
And:
final_cipher = str(final_cipher) + str(new_letter)
Should be:
final_cipher = final_cipher + str(new_letter)
Or better:
final_cipher += str(new_letter)
final_cipher is a list, so yes, printing it will print it as a string, i.e. the result of calling str(final_cipher).
If you want to just print the elements seperated by a comma, you can use .join:
print ", ".join(final_cipher)
You create final_cipher as a list but then change your mind and do string concatenation instead. On the first iteration of the loop, str(final_cipher) creates the string representation of an empty list "[]". Look familiar? Keep a list and build the string at the end.
final_cipher = []
loop = 0
alphabet = string.ascii_lowercase + " " + string.ascii_lowercase + " "
while loop < len(final_positions_of_letters):
new_letter =alphabet[final_positions_of_letters[loop]]
final_cipher.append(str(new_letter))
loop += 1
final_cipher = ''.join(final_cipher)
print final_cipher
Over at this question there are some neat tricks for generating functions on the fly in Python.
In my use case, however, I need to make sure the generated function has a particular name and particularly-named arguments as well. I'll give an example.
Suppose I want to parse a Yaml file that has a format like this:
Root:
my_idea:
type: conditional
conditionals:
- foo
- bar
query: >
SELECT * FROM some_table
This needs to be interpreted as: create a function for me called "my_idea" which has arguments named "foo" and "bar" (in that order).
When the function is called, use some existing tool to connect to a database and prepare the query element from the Yaml file. Then add a WHERE clause based on the conditional names matching the values passed in to the function for that argument.
So, after this happens, a user should be able to call:
my_idea(10, 20)
and it would be equivalent to executing the query
SELECT * FROM some_table WHERE foo = 10 AND bar = 20
If I used def to make the function, it might be something like this:
def my_idea(arg1, arg2):
query = (query_retrieved_from_file +
" WHERE {}={} AND {}={}".format(arg1_name_from_file,
arg1,
arg2_name_from_file,
arg2))
connection = ExistingLibraryConnectionMaker()
return connection.execute(query).fetchall()
This is a really simplified example -- I'm not endorsing the specifics of this little function, just trying to illustrate the idea.
The question is: how to create this on-the-fly, where the name of the function and the name of the positional arguments are extracted from a text file?
In the other question, there is some example code:
import types
def create_function(name, args):
def y(): pass
y_code = types.CodeType(args,
y.func_code.co_nlocals,
y.func_code.co_stacksize,
y.func_code.co_flags,
y.func_code.co_code,
y.func_code.co_consts,
y.func_code.co_names,
y.func_code.co_varnames,
y.func_code.co_filename,
name,
y.func_code.co_firstlineno,
y.func_code.co_lnotab)
return types.FunctionType(y_code, y.func_globals, name)
but it's not clear how to have the positional args reflect what I want them to semantically reflect.
The other solution I found was like this:
import types
import sys,imp
code = """def f(a,b,c):
print a+b+c, "really WoW"
"""
module = imp.new_module('myfunctions')
exec code in module.__dict__
module.f('W', 'o', 'W')
Output:
WoW really WoW
This is much closer, but requires all of the code to be embedded in a string format. I'm looking to build up a function programmatically, and across a reasonably large set of options, so handling them all deep in strings is not doable.
LL Parser example, made for fun.
Generates
Generated Code:
def my_idea(arg0,arg1,atasdasd):
query = "SELECT * FROM some_table WHERE foo==arg0 AND bar>arg1"
connection = ExistingLibraryConnectionMaker()
return connection.execute(query).fetchall()
def lool(hihi,ahah):
query = "SELECT * FROM some_table WHERE foo<=hihi AND bar<ahah"
connection = ExistingLibraryConnectionMaker()
return connection.execute(query).fetchall()
###end
from
Root:
my_idea:
args :
-arg0
-arg1
-atasdasd
type: conditional
conditional:
-foo == arg0
-bar > arg1
query:
SELECT * FROM some_table
lool:
args :
-hihi
-ahah
type: conditional
conditional:
- foo <= hihi
- bar < ahah
query:
SELECT * FROM some_table
Can handle any number of functions.
Code:
from __future__ import print_function
import re
import traceback
import sys
glIndex = 0
code = ""
class Token(object):
def __init__(self, pattern, name, value=None, transform=None):
self.pattern = pattern
self.name = name
self.value = value
tokens = {
Token(r"(\()","lpar"),
Token(r"(\))","rpar"),
Token(r"(\d(?:\.\d*)?)","number"),
Token(r"(\+)", "plus"),
Token(r"(?!\-\-)(\-)","minus"),
Token(r"(?!\=\=)(\=)","egal"),
Token(r"(;)","colon"),
Token(r"([a-zA-Z][a-zA-Z0-9_]*)(?=[\s\:])","unique"),
Token(r"(\=)\=","=="),
Token(r"(\>\=)",">="),
Token(r"(\<\=)","<="),
Token(r"(?!\>\=)(\>)",">"),
Token(r"(?!\<\=)(\<)","<"),
Token(r"\:",":"),
Token(r"\*","*")}
def peekComp(l):
symbol = None
if peekMatch(l,">=") :
symbol = ">="
elif peekMatch(l,"<=") :
symbol = "<="
elif peekMatch(l,">") :
symbol = ">"
elif peekMatch(l,"<") :
symbol = "<"
elif peekMatch(l,"==") :
symbol = "=="
return symbol
def parseListItem(l):
match(l,"minus")
u = match(l,"unique")
return u
def parseTitle(l):
val = match(l,"unique")
match(l,":")
return val
def parseComp(l):
match(l,"minus")
lvar = match(l,"unique")
symbol = peekComp(l)
if symbol == None:
print("Homemaid SyntaxError: needed a comp symbol")
exit(1)
symbolS = match(l,symbol)
rvar = match(l,"unique")
return (lvar,symbolS,rvar)
def tokenize(s):
l=[]
i=0
while i < s.__len__():
if re.match(r"\s",s[i]):
i+=1
continue
foundAMatch = False
for t in tokens:
pat = "^(" + t.pattern + ").*"
#print("trying with pat :'"+pat+"';")
res = re.match(pat,s[i:])
if res != None:
print("Match: -what : '" + res.group(1) + "' -to-token-named :'" + t.name + "'; \t\tTotal text : '" + res.group(0) + "';" )
i += res.group(1).__len__()
foundAMatch = True
l.append(Token(t.pattern,t.name,res.group(1)))
break
if not foundAMatch:
print("Homemaid SyntaxError: No match for '" + s[i:] + "';")
quit()
return l
def syntaxError(l,fname):
global glIndex
print("Homemaid SyntaxError: '"+l[glIndex].name+"'")
print(fname)
quit()
def match(tokens, wanted):
global glIndex
if tokens[glIndex].name == wanted:
glIndex+=1
print("Matched '" + tokens[glIndex-1].value + "' as '" + wanted + "';")
return tokens[glIndex-1].value
else:
print("Homemaid Syntax Error : Match failed on token '" + tokens[glIndex].name + "' with wanted token '" + wanted + "' and text '" + tokens[glIndex].value + "';")
exit(1)
def peekMatch(token, wanted):
global glIndex
if glIndex < token.__len__() and token[glIndex].name == wanted:
print("Matched "+wanted)
return True
else:
return False
def parse(l):
#root
localCode = ""
rootName = parseTitle(l)
print("Root : " + rootName)
#parse funcitons
while peekMatch(l,"unique"):
localCode += parseFunction(l)
print("Done with the parsing.")
return localCode
def parseFunction(l):
print("CAME IN PARSE FUNCITON")
#function name
localCode = "\n\ndef " + parseTitle(l) +"(";
#args
args = set()
title = parseTitle(l)
if title!="args":
print("Homemaid Syntax Error : title should be 'args', was instead '" + title + "';")
exit(1)
while(peekMatch(l,"minus")):
lastArg = parseListItem(l)
args.add(lastArg)
localCode += lastArg
if peekMatch(l,"minus") :
localCode += ","
localCode += "):\n"
#type
if parseTitle(l)!="type":
print("Homemaid Syntax Error : title should be 'type'")
exit(1)
#query
##query name
queryTypeName = match(l, "unique")
##query args
queryTypeArgs = []
if parseTitle(l)!=queryTypeName:
print("Homemaid Syntax Error : title should be the same as the name of the query.")
exit(1)
while(peekMatch(l,"minus")):
queryTypeArgs.append(parseComp(l))
##query sql code
if parseTitle(l) != "query":
print("Homemaid Syntax Error : title should be 'query'.")
exit(1)
initialQuery = parseBasicSqlQuery(l)
if queryTypeName == "conditional" and queryTypeArgs.__len__() <= 0 :
print("Homemaid Syntax error : Conditional query needs at least one arg.")
exit(1)
##query codegen
localCode += "\tquery = \"" + initialQuery + " WHERE "
first = True
if queryTypeName == "conditional":
for lArg, cmpSign, rArg in queryTypeArgs:
if not first:
localCode += " AND "
if rArg in args:
first = False
localCode += lArg + cmpSign + rArg
else:
print("queryTypeArgs : " + str(queryTypeArgs))
print("Homemaid Logic Error: Query arg '" + rArg + "' is not in the funciton args " + str(args) + ".")
quit(1)
localCode += "\"\n\tconnection = ExistingLibraryConnectionMaker()\n\treturn connection.execute(query).fetchall()"
return localCode
def parseBasicSqlQuery(l):
selectS = match(l,"unique")
whatS = match(l,"*")
fromS = match(l,"unique")
tableNameS = match(l,"unique")
if selectS.upper() != "SELECT" or fromS.upper() != "FROM":
print("Homemaid Syntax error: bad basic sql.")
exit(0)
return selectS + " " + whatS + " " + fromS + " " + tableNameS
def parseVal(l):
if match(l, "lpar"):
parseVal(l)
match(l, "rpar")
elif peekMatch(l, "number") and (peekMatch(l, "plus") or peekMatch(l, "minus") or peekMatch(l, "equal")):
glIndex+=1
print("peekMatched!")
parseOp(l)
parseVal(l)
elif match(l, "number"):
pass
else:
syntaxError(l, "parseVal")
print("** Parsed val.")
def parseOp(l):
if match(l, "plus"):
pass
elif match(l, "minus"):
pass
elif match(l, "egal"):
pass
else:
syntaxError(l, "parseVal")
print("** Parsed op.")
if __name__ == "__main__":
with open("sqlGenTest.SQLGEN", "rw") as file:
print("File:\n'")
text = file.read()
print(text + "'\n")
tokens = tokenize(text)
names = map(lambda x: str("'" + x.name + "'" + " : " + "'" + x.value + "'"), tokens)
map(print,names)
code = parse(tokens)
print("")
print("###Generated Code:\n" + code)
print("###end")
print()