Pass variables to another module which contains classes - python

I have a module with a Class
class Record(object):
Name = ''
Gender = ''
Age = ''
Line = 'Bob=Male=40'
M = Line.split('=')
exec(M[0] + ' = ' + 'Record()')
exec(M[0] + '.' + 'Name' + ' = ' + "'" + M[0] + "'")
exec(M[0] + '.' + 'Gender' + ' = ' + "'" + M[1] + "'")
exec(M[0] + '.' + 'Age' + ' = ' + "'" + M[2] + "'")
I am trying to import the above module but to pass it the "Line" variable.
How could I do that ?

Adding this one line should do the job
# in main script
from lib import file_name
file_name.Line = Line #Assuming line is declared already
you need not declare Line in your module

You create objects by calling a class. You don't need to use exec to do that
#record.py
class Record:
def __init__(self, name, gender, age):
self.Name = name
self.Gender = gender
self.Age = age
def __str__(self):
return ' '.join((self.Name, self.Gender, self.Age))
Person = Record("Bob", "Male", "30")
# workspace.py
import record
print(record.Person)
Person2 = record.Record("Alice", "F", "30")
print(Person2)
Outputs:
Bob M 30
Alice F 30
In python you probably would get away with this
name = "Bob"
gend = "M"
age = '30'
exec(f'{name} = record.Record("{name}", "{gend}", "{age}")')
print(Bob)
# Bob M 30
But I would not advise that

Related

Correct usage of __str__ method for a dictionary (kwargs)

I have a task to print correctly kwargs arguments of a class.
Here is my code:
class Contact:
def __init__(self, name, surname, number, selected=None, **kwargs):
self.name=name
self.surname=surname
self.number=number
self.selected=selected
self.additional=kwargs
def __str__(self):
if self.selected==None:
selected='No'
else:
selected='Yes'
return 'Name: ' + self.name+'\n' + \
'Surname: ' + self.surname+ '\n' + \
'Phone: ' + self.number + '\n' + \
'In selected: ' + selected + '\n' + \
'Additional information: ' + '\n' + \
str(self.additional.keys()) + '\n' + \
str(self.additional.values())
if __name__=='__main__':
jhon = Contact('Jhon', 'Smith', '+71234567809', telegram='#jhony', email='jhony#smith.com')
print (jhon)
I need to have in the end:
Additional information:
telegram : #jhony
email : jhony#smith.com
But all I've got is :
I've really tried to iterate over it, create lists, and I've got nothing, because the ___str___ method could only use str objects. How can I go through the kwargs arguments and take it in format of key : value?
You need to iterate over the dict referenced by self.additional.
def __str__(self):
return ('Name: ' + self.name + '\n'
+ 'Surname: ' + self.surname+ '\n' +
+ 'Phone: ' + self.number + '\n' +
+ 'In selected: ' + selected + '\n' +
+ 'Additional information: ' + '\n' +
+ '\n'.join([f' {k}: {v}' for k, v in self.additional.items()]))

How can I write this to a file

class PersonalInfo:
def set_titles(self, title):
self.__titles = title
def set_names(self, name):
self.__names = name
def set_addresses(self, add):
self.__addresses = add
def set_ages(self, age):
self.__ages = age
def set_numbers(self, number):
self.__numbers = number
# Accessor methods
def get_titles(self):
return self.__titles
def get_names(self):
return self.__names
def get_addresses(self):
return self.__addresses
def get_ages(self):
return self.__ages
def get_numbers(self):
return self.__numbers
def main():
# references PersonalInfo object
info = PersonalInfo()
# stores values in the object
info.set_titles(input("Enter Mr, Mrs, Miss:"))
info.set_names(input("Enter full name:"))
info.set_addresses(input("Enter address:"))
info.set_ages(input("Enter age:"))
info.set_numbers(input("Enter number:"))
#displays values stored in object's fields
print("Name: " + info.get_titles() + " " + info.get_names() + "\n"
+"Address: " + info.get_addresses() + "\n"
+ "Birth: " + info.get_ages() + "\n"
+ "Number: " + info.get_numbers() + "\n")
main()
main()
I want this to be printed out 2 times since I have 2 users who will answer the questions, but I can't seem to understand how to save the input answers in a text file. Can someone please give me an example??:)
I'm such a noob at this
Change your main() to init(self): And call it twice if you need run it twice. You could write a method to output the data to a file instead of including it in init if you wanted to.
def __init__(self):
# stores values in the object
self.title = self.set_titles(input("Enter Mr, Mrs, Miss: "))
self.name = self.set_names(input("Enter full name: "))
self.age = self.set_ages(input("Enter age: "))
self.address = self.set_addresses(input("Enter address: "))
self.number = self.set_numbers(input("Enter number: "))
# displays values stored in object's fields
print("Name: " + self.get_titles() + " " + self.get_names() + "\n"
+"Address: " + self.get_addresses() + "\n"
+ "Birth: " + self.get_ages() + "\n"
+ "Number: " + self.get_numbers() + "\n")
# Appends data to file
outfile = open('data_from_user.txt','a')
outfile.write("Name: " + self.get_titles() + " " + self.get_names() + "\n")
outfile.write("Address: " + self.get_addresses() + "\n")
outfile.write("Birth: " + self.get_ages() + "\n")
outfile.write("Number: " + self.get_numbers() + "\n")
outfile.close()
person_1 = PersonalInfo()
person_2 = PersonalInfo()
# storing data inside string
string = 'NAME: {} \n Address: {} \n Birth: {} \n Number: {} \n'.format(info.get_titles(),info.get_names(),
info.get_addresses(),info.get_ages(),info.get_numbers())
# printing 2 times
print(string,string,sep='\n')
# writing in a file
x = open('filename','a')
x.write(string)
x.close()

Python printing objects - TypeError: must be str, not Address

I have Person and Address classes. Each Person holds an Address.
Code:
class Address:
def __init__(self, street, town, city, postcode, country):
self.street = street
self.town = town
self.city = city
self.postcode = postcode
self.country = country
def __str__(self):
return ("\t" + "Street: " + self.street +
"\n\t" + "Town: " + self.town +
"\n\t" + "City: " + self.city +
"\n\t" + "Postcode: " + self.postcode +
"\n\t" + "Country:" + self.country)
class Person:
def __init__(self, name, age, phone, address):
# instance variables, unique to each Person
self.name = name
self.age = age
self.phone = phone
self.address = address
def __str__(self):
return "Name: " + self.name + "\n" + "Age: " + self.age + "\n" + "Phone: " + self.phone + "\n" + "Address: " + self.address
However, when I call print(p) where p is a Person, I get the following exception:
File "phone2.7.py", line 30, in __str__
return "Name: " + self.name + "\n" + "Age: " + self.age + "\n" + "Phone: " + self.phone + "\n" + "Address: " + self.address
TypeError: must be str, not Address
Can anyone pinpoint what the issue is here? Thanks.
You are trying to add string and object. It's not enough that you override the __str__ method in your Address class. You need to call str() method.
"Address: " + str(self.address)
class Address:
def __init__(self, street, town, city, postcode, country):
self.street = street
self.town = town
self.city = city
self.postcode = postcode
self.country = country
def __str__(self):
return ("\t" + "Street: " + self.street +
"\n\t" + "Town: " + self.town +
"\n\t" + "City: " + self.city +
"\n\t" + "Postcode: " + self.postcode +
"\n\t" + "Country:" + self.country)
class Person:
def __init__(self, name, age, phone, address):
# instance variables, unique to each Person
self.name = name
self.age = age
self.phone = phone
self.address = address
def __str__(self):
return "Name: " + str(self.name) + "\n" + "Age: " + str(self.age) + "\n" + "Phone: " + str(self.phone) + "\n" + "Address: " + str(self.address)
p = Person(1,2,3,4)
print p
Before concatenating using +, the self.address object must be converted to string using str() function.
class Person:
def __str__(self):
return "Name: " + self.name + "\n" + "Age: " + self.age + "\n" + "Phone: " + self.phone + "\n" + "Address: " + str(self.address)

using a function to call a class in a while loop

I'm currently writing a python gui that will ultimately generate a random village for use in tabletop RPG (mainly dungeons and dragons)
I have the code below that will generate a number of taverns based on how big a town the user wants and so far it works fine. I hope the GUI will eventually create shops, temples and other buildings too.
class NPC:
def __init__(self, first, last):
self.first = first
self.last = last
self.name = first + ' ' + last
class Tavern:
def __init__(self, name1, name2):
self.name1 = name1
self.name2 = name2
self.name = 'The ' + name1 + ' ' + name2
while num_tav != 0:
morf = random.randint(1, 2)
if morf == 1:
sex = 'male'
else:
sex = 'female'
first = open(set_race + '_' + sex + '.txt')
name1 = first.readlines()
first = random.choice(name1).strip()
last = open(set_race + '_surnames.txt')
name2 = last.readlines()
last = random.choice(name2).strip()
npcname = NPC(first, last)
tavern1 = open('tavnames1.txt')
name1 = tavern1.readlines()
name1 = random.choice(name1).strip()
tavern2 = open('tavnames2.txt')
name2 = tavern2.readlines()
name2 = random.choice(name2).strip()
tavern = Tavern(name1, name2)
print('Taverns/Inns: ' + tavern.name + "The inkeeper is a tall " + set_race + ' ' + sex + " named " + npcname.name + '\n')
num_tav = num_tav - 1
w.insert(END, not_b + 'Taverns/Inns: ' + tavern.name + "The inkeeper is a tall " + set_race + ' ' + sex + " named " + npcname.name + '\n' + 'Population is approx. ' + str(population) + ' people\n')
The NPC class basically genreates a random name and I'd like to use this in other areas (shops, markets, blacksmith, etc.), not just to generate the name of an innkeeper.
My question is;
Is it possible to create a function that will use the script
first = open(set_race + '_' + sex + '.txt')
name1 = first.readlines()
first = random.choice(name1).strip()
last = open(set_race + '_surnames.txt')
name2 = last.readlines()
last = random.choice(name2).strip()
npcname = NPC(first, last)
as a function that will call the NPC class, and then just have other while loops calls it? Instead of having the same code repeated in each of the loops I'll use to generate other buildings?
I'm assuming so but I just don't know what it would be called so any help is appreciated.
define the while loop in a function with maybe an extra parameter that gets the type of entity that it is supposed to generate (Tavern, shop,...) and then put it in another python file and import it. as a module.
def mynewfunction(set_race,sex):
first = open(set_race + '_' + sex + '.txt')
name1 = first.readlines()
first = random.choice(name1).strip()
last = open(set_race + '_surnames.txt')
name2 = last.readlines()
last = random.choice(name2).strip()
return NPC(first, last)
Then:
while (x,y,z):
npcname = mynewfunction(set_race):

Dynamically create a Python function with positional or key-word args, not from a string

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

Categories