I'm playing around and testing data structure and noticed you could print a list inside a class or a def function if you do class.list[0] or def.list[0], so I tried seeing how deep it could go and adding func inside func inside the class but instead of my expectation to just add more dots to the end of the value to chain them, it seems it doesn't work past 1 value.
class player:
def __init__(self, name, spec):
self.name = name
self.spec = spec
var1 = ('A1','A2')
def def1():
defA = "printed defA"
def def2():
defB = ('B1','B2')
print(player.def1.def2.defB[0]) #Doesn't work---
print(player.var1[0]) #Works fine---
In this case, would there be a way to print (or anything else) to the values nested deep in there? What would the address of this value be?
Related
I am running multiple scenarios for my experiment, which requires me to dynamically change the variable names depending upon the Scenario and Class. For that, I have got a few lines of working code, where changing simulations (i.e., Scenario and Class) changes the variable names. However, this code needs to be called everytime after I define my experiment. Code below:
# Funtion
def Moisture_transport(Scenario, Class, delta_crop):
""" (unrelated to this question) """
return Class_direct, Class_sum_cmr
""" Define the Scenario and Class """
Scenario = 2; Class = 1; delta_crop = True # Assign the Scenario, Class and delta_crop
## Few lines of code that needs to run every time without any change
if delta_crop == False:
vars()['Moisture_direct_Scenario_'+str(Scenario)+'_Class_'+str(Class)], vars()['Moisture_with_CMR_Scenario_'+str(Scenario)+'_Class_'+str(Class)] = Moisture_transport(Scenario, Class, delta_crop)
else:
vars()['Moisture_direct_Scenario_'+str(Scenario)+'_Class_'+str(Class)+'_deltacrop'], vars()['Moisture_with_CMR_Scenario_'+str(Scenario)+'_Class_'+str(Class)+'_deltacrop'] = Moisture_transport(Scenario, Class, delta_crop)
Does any one know how to make vars()['variable_name'] global in the function Moisture_transport?
I think this can be simpler still. There is some cost to handling a key so I'd not make them excessively long. Please note the global, where it is and is not used.
Moisture_variables = {}
def Moisture_transport(Scenario, Class, delta_crop):
global Moisture_variables
""" (unrelated to this question) """
#return Class_direct, Class_sum_cmr
Moisture_variables[f"{Scenario} {Class} {delta_crop}"] = (Class_direct, Class_sum_cmr)
You can also sub-dictionary the results although this creates a bit of overhead to checking if sub-dictionaries exist. Note I've deliberately changed (shortened) the variables in the called function to make it clear these are in a different scope.
Moisture_variables = {}
def Moisture_transport(Scenario, Class, delta_crop):
""" (unrelated to this question) """
#return Class_direct, Class_sum_cmr
add_Moisture_Variables(Scenario, Class, delta_crop, Class_direct, Class_sum_cmr)
def add_Moisture_variables(s, c, d, cd, cs):
global Moisture_variables
if s not in Moisture_variables:
Moisture_variables[s] = {}
if c not in Moisture_variables[s]:
Moisture_variables[s][c] = {}
Moisture_variables[s][c][d] = (cd, cs)
Yet another approach if a list works, the double bracket to append a tuple are important.
Moisture_variables = []
def Moisture_transport(Scenario, Class, delta_crop):
global Moisture_variables
""" (unrelated to this question) """
#return Class_direct, Class_sum_cmr
Moisture_variables.append((Scenario, Class, delta_crop, Class_direct, Class_sum_cmr))
The choice of which approach works best depends on how you wish to recover the data.
Defining a dictionary is more efficient in the following case to hold all the variables as string, which can be called with conditions, i.e., Scenario or Class.
#Add a last line to the original function
def Moisture_transport(Scenario, Class, delta_crop):
""" (unrelated to this question) """
#return Class_direct, Class_sum_cmr
variables_dict(Class_direct, Class_sum_cmr,delta_crop)
#Add a normal dictionary and a variable name defining funtion
Moisture_variables = {}
def variables_dict(Class_direct, Class_sum_cmr, delta_crop):
if delta_crop == False:
Moisture_variables['Moisture_direct_Scenario_{0}_Class_{1}'.format(Scenario,Class)] = Class_direct
Moisture_variables['Moisture_with_CMR_Scenario_{0}_Class_{1}'.format(Scenario,Class)] = Class_sum_cmr
else:
Moisture_variables['Moisture_direct_Scenario_{0}_Class_{1}_deltacrop'.format(Scenario,Class)] = Class_direct
Moisture_variables['Moisture_with_CMR_Scenario_{0}_Class_{1}_deltacrop'.format(Scenario,Class)] = Class_sum_cmr
After that, you can run the function Moisture_transport() as it is, and not worry about defining the variables outside the function, i.e., code after ## Few lines of code that needs to run every time without any change from the original question is not needed. E.g.:
""" Define the Scenario and Class """
Scenario = 1; Class = 0; delta_crop = False
Moisture_transport(Scenario, Class, delta_crop)
Here is my class code:
class Example:
def __init__(self):
self.parameter1 = 1
def standardFunction(self):
print("Hello")
Is it possible to initialise the Example class and make sure that every method that may be called for this particular instance will always point to the standardFunction?
For example:
ex1 = Example()
ex1.test1()
prints "Hello"
ex1.test2()
prints "Hello"
ex1.test3.test4()
prints "Hello"
ex1.test5().test6().IamBatman(42)
prints "Hello"
Basically, I would like to always have the Example.standardFunction() called, disregarding the string after the first "dot". Plus I don't know what's being put after the dot - it may be any string, int, float, or null.
Is it possible to achieve such behaviour with Python?
Yes we can achieve similar behavior in Python by overloading __getattr__. Like this,
class Example:
def __init__(self):
self.parameter1 = 1
def standardFunction(self):
print("Hello")
def __getattr__(self, name):
return self.standardFunction
So I am getting used to working with OOP in python, it has been a bumpy road but so far things seem to be working. I have, however hit a snag and i cannot seem to figure this out. here is the premise.
I call a class and pass 2 variables to it, a report and location. From there, I need to take the location variable, pass it to a database and get a list of filters it is supposed to run through, and this is done through a dictionary call. Finally, once that dictionary call happens, i need to take that report and run it through the filters. here is the code i have.
class Filters(object):
def __init__ (self, report, location):
self.report = report
self.location = location
def get_location(self):
return self.location
def run(self):
cursor = con.cursor()
filters = cursor.execute(filterqry).fetchall()
for i in filters:
f = ReportFilters.fd.get(i[0])
f.run()
cursor.close()
class Filter1(Filters):
def __init__(self):
self.f1 = None
''' here is where i tried super() and Filters.__init__.() etc.... but couldn't make it work'''
def run(self):
'''Here is where i want to run the filters but as of now i am trying to print out the
location and the report to see if it gets the variables.'''
print(Filters.get_location())
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(),
'filter_2': Filter2(),
'filter_3': Filter3()
}
My errors come from the dictionary call, as when i tried to call it as it is asking for the report and location variables.
Hope this is clear enough for you to help out with, as always it is duly appreciated.
DamnGroundHog
The call to its parent class should be defined inside the init function and you should pass the arguments 'self', 'report' and 'location' into init() and Filters.init() call to parent class so that it can find those variables.
If the error is in the Filters1 class object, when you try to use run method and you do not see a location or a report variable passed in from parent class, that is because you haven't defined them when you instantiated those object in ReportFilters.fd
It should be:
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(report1, location1),
'filter_2': Filter2(report2, location2),
'filter_3': Filter3(report3, location3)
}
class Filter1(Filters):
def __init__(self, report, location):
Filters.__init__(self, report, location)
self.f1 = None
def run(self):
print(self.get_location())
So I am very new to coding and started with python, I am trying to build a class in a program that puts together a DnD party by randomising their attributes. So far I can get the program to initialise instances of the party members and just give the user a prompt on how many of the hero's to choose from they would like in their party. My issue is that after setting the lists up and getting everything in place. I am unable to print any of the attributes of the individual heros. Regardless of whether I am calling them from within the lists or if I am directly trying to print them. I have tried using __str__ to create strings of the attributes but I am clearly missing something. Any help would be greatly appreciated.
import random
class Party:
def __init__(self, name="", race="", alignment="", class_=""):
self.name = name
while name == "":
name = random.choice(names)
# print(name)
self.race = race
while race == "":
race = random.choice(races)
# print(race)
self.alignment = alignment
while alignment == "":
alignment = random.choice(alignments)
# print(alignment)
self.class_ = class_
while class_ == "":
class_ = random.choice(classes)
# print(class_)
def character_stats(self):
return "{} - {} - {} - {}".format(self.name, self.race, self.class_, self.alignment)
Each attribute pulls a random value from a list. My format statement is the latest attempt to get the values of the attributes to print rather than the object/attributes instead.
I apologise if any of the terminology is wrong, very very new to this
You are not assigning anything else but the input, (in this case being an empty string "" to the attribuytes. In your minimal example you have this constructor:
class Party:
def __init__(self, name=""):
self.name = name
while name == "":
name = random.choice(names)
After you randomly assign a new name from names, you should assign it to self, otherwise the local variable just goes out of scope when the __init__ method finishes. This code snippet should work:
class Party:
def __init__(self, name=""):
while name == "":
name = random.choice(names)
# Now we assign the local variable as
# an attribute
self.name = name
Sorry if the title is confusing. I'm writing a minimalist game engine, and trying to define a class called "Area" where if the player enters the area, a function defined by the user happens. For example, one could create an instance
Area(location,function) that would fire function on the player when the player enters location (for the sake of simplicity, let it be a point or something).
Note: in pseudo-python
# in init.py
...
def function(player):
kill player
deathZone = Area(location,function)
--------------------------------------
# in player.update()
...
for area on screen:
if player in area:
Area.function(player)
The point of this is that the developer (aka me) can use any function they choose for the area. Is there anyway to do this, or should I try a better approach?
Sure, this kind of thing is certainly possible. In python, everything is an object, even a function. So you can pass around a function reference as a variable. For example try the following code:
import math
def rectangle(a, b):
return a*b
def circle(radius):
return math.pi * radius**2
class FunctionRunner(object):
def __init__(self):
self.userFunction = None
self.userParams = None
def setUserFunction(self, func, *params):
self.userFunction = func
self.userParams = params
def runFunction(self):
return self.userFunction(*self.userParams)
if __name__ == '__main__':
functionRunner = FunctionRunner()
functionRunner.setUserFunction(rectangle, 6, 7)
print(functionRunner.runFunction())
functionRunner.setUserFunction(circle, 42)
print(functionRunner.runFunction())
Here you have two functions that are defined for an area, and a class called FunctionRunner which can run any function with any number of input arguments. In the main program, notice that you need only pass the reference to the function name, and any input arguments needed to the setUserFunction method. This kind of thing will allow you to execute arbitrary code on the fly.
Alternatively, you could also replace a method on your class with a reference to another function (which is what you are asking), though this seems less safe to me. But it is certainly possible. For example you could have a class like this:
class FunctionRunner2(object):
def __init__(self):
pass
def setUserFunction(self, func):
self.theFunction = func
def theFunction(self, *params):
pass
And then do this:
if __name__ == '__main__':
functionRunner2 = FunctionRunner2()
functionRunner2.setUserFunction(rectangle)
print(functionRunner2.theFunction(6,7))
functionRunner2.setUserFunction(circle)
print(functionRunner2.theFunction(42))