I want to create a structure, as we do in C, in python. I have tried to use namedtuple() for this. However, I can not update the values of variables I have described inside the custom structure.
Here is how i declared it:
from collections import namedtuple as nt
Struct = nt('Struct','all left right bottom top near far')
And this is what i am trying to do in a method :
class codeClip:
def compOutCode(x,y,z,xmin,xmax,ymin,ymax,zmin,zmax):
code = Struct(0,0,0,0,0,0,0)
if(y > ymax):
code.top = 1
code.all += code.top
elif(y < ymin):
code.bottom = 1
return code
However it is giving this error:
code.top = 1
AttributeError: can't set attribute
What should I do? Pardon me, I am fairly new in python, so still getting used to all of these.
You may use the _replace() method.
Instead of code.top = 1, you can update values as follows.
code = code._replace(top = 1)
Please note, named tuples are immutable, so you cannot manipulate them. If you want something mutable, you can use recordtype.
Reference: https://stackoverflow.com/a/31253184/5352399
Related
I want to to store a reference to a class object inside a dictionary or another class that will maintain the same value as the actual class object. Currently, I'm using a string of the class object and the eval() function. I know this isn't a proper solution but haven't found another fix.
curWeapon is a object of WeaponInfo with pveFlag and pvpFlag variables
ListSetting stores the boolean expression of curWeapon along with a,b,c...
wishLists is passed to the main class of the program which reads a file and changed the pve/pvpFlags
When a empty line is read the boolean expression is evaluated with the new flags
wishLists.append(ListSetting("curWeapon.pveFlag or not curWeapon.pvpFlag", a, b, c, d))
My only idea is making a new function that has separates the boolean expression from a,b,c.. when making the ListSetting and adding that separately. Although I'm not sure if wishLists would update the firstFlag, secondFlag... variables.
firstFlag = ListSetting(a,b,c,d)
wishLists.append(firstFlag)
def wishListFlags():
firstFlag.flags = curWeapon.pveFlag or not curWeapon.pvpFlag
secondFlag.flags = ""
...
I'm pretty sure that updating the index of wishLists would work but would need a bunch of if statements or a dictionary.
firstFlag = ListSetting(a,b,c,d)
wishLists.append(firstFlag)
flagExpressions = {
1 : curWishListcurWeapon.pveFlag or not curWeapon.pvpFlag,
2 : "",
...}
def wishListFlags():
for index in len(wishLists):
wishLists[index].flags = flagExpressions.get(index)
If anyone knows a better way to go about this please let me know. Also, if my examples aren't specific enough or are confusing I'd be happy to share my entire program, I didn't know if it would be too much.
To store an expression you use a function, which you later call to get the value of the expression.
flagExpressions = {
1: lambda: curWishListcurWeapon.pveFlag or not curWeapon.pvpFlag
2: lambda: ""
}
def wishListFlags():
for index in len(wishLists):
wishLists[index].flags = flagExpressions.get(index, lambda: None)()
I have three similar functions in tld_list.py. I am working out of mainBase.py file.
I am trying to create a variable string which will call the appropriate function by looping through the list of all functions. My code reads from a list of function names, iterates through the list and running the function on each iteration. Each function returns 10 pieces of information from separate websites
I have tried 2 variations annotated as Option A and Option B below
# This is mainBase.py
import tld_list # I use this in conjunction with Option A
from tld_list import * # I use this with Option B
functionList = ["functionA", "functionB", "functionC"]
tldIterator = 0
while tldIterator < len(functionList):
# This will determine which function is called first
# In the first case, the function is functionA
currentFunction = str(functionList[tldIterator])
Option A
currentFunction = "tld_list." + currentFunction
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Option B
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Even though it is not seen, I continue to loop through the iteration by ending each loop with tldIterator += 1
Both options fail for the same reason stating TypeError: 'str' object is not callable
I am wondering what I am doing wrong, or if it is even possible to call a function in a loop with a variable
You have the function names but what you really want are the function objects bound to those names in tld_list. Since function names are attributes of the module, getattr does the job. Also, it seems like list iteration rather than keeping track of your own tldIterator index would suffice.
import tld_list
function_names = ["functionA", "functionB", "functionC"]
functions = [getattr(tld_list, name) for name in function_names]
for fctn in functions:
website_name = fctn(x,y)
You can create a dictionary to provide a name to function conversion:
def funcA(...): pass
def funcB(...): pass
def funcC(...): pass
func_find = {"Huey": funcA, "Dewey": funcB, "Louie": FuncC}
Then you can call them, e.g.
result = func_find["Huey"](...)
You should avoid this type of code. Try using if's, or references instead. But you can try:
websiteName = exec('{}(x, y)'.format(currentFunction))
Hello :) I'm using two modules in Python: Module 1 (for creating a nested data structure) and Module 2 (for accessing the "fields" of the structure and, very important, I want Python to show me the fields while I'm typing in Module 2 as there will be a lot of fields in Module 1). The nested structure is like that:
NAME A
value: 5
NAME B
value: 6
NAME B2
Value:76
NAME C
Index: 78
I've been studying if using a list, a dictionary, a tuple... so far, I've seen named tuples may be the right solution because of immutability and using names for identifiers, instead of numbers. My code in Module 1 is:
from collections import namedtuple
def ModbusDiction():
NameA = namedtuple('NameA', ['value','NameB','NameC'])
NameB = namedtuple('NameB', ['value','NameB2'])
NameB2 = namedtuple('NameB2','value')
NameC = namedtuple('NameC','index')
NameC_value = NameC(78)
NameB2_value = NameB2(76)
NameB_value = NameB(6, NameB2_value)
NameA_value = NameA(5,NameB_value,NameC_value)
return NameA_value
My code in Module 2 (Files_CommonUse.folder_ModbusIndex.indexModbus is the path of module 1) is:
import Files_CommonUse.folder_ModbusIndex.indexModbus as index_modbus
indexmodbus = index_modbus.ModbusDiction()
print(indexmodbus.NameB.NameB2.value)
The resulf from the print is 76, so it's working. However, while I was typing indexmodbus., the "field" NameA did not appear. While I was typing indexmodbus.NameA., I would have liked to be shown value,NameB or NameC, but nothing was displayed. I wonder if this named tuple has become mutable. I'm using Eclipse, by the way.
Please, could anybody help me on this? :) Maybe the idea of named tuple does not work for my interest or I'm using the concept in a wrong way :S
I would've used my custom class to create my custom data structure instead, because it's more flexible than namedtuples
def mod_bus_diction(**kwargs):
return type('MyStructure', (), {**kwargs})
MyStructure = mod_bus_diction(
value=5,
NameB=mod_bus_diction(
value=6,
NameB2=mod_bus_diction(
value=76
)
),
NameC=mod_bus_diction(
index=78
)
)
I checked it on ipython terminal it was suggesting the values and properties. I didn't check on eclipse by the way.
As named tuples are a kind of light weight object, they behave like objects. That means, NameA_value is an instantiation of the NameA tuple object and if you return that instance from a function, the new variable becomes that instance. So your indexmodbus is an instance of the NameA tuple object.
If you want to do: indexmodbus.NameA, you need another step above NameA, your function could then look like this:
def ModbusDiction():
TopTuple = namedtuple('top', ['NameA'])
NameA = namedtuple('NameA', ['value','NameB','NameC'])
NameB = namedtuple('NameB', ['value','NameB2'])
NameB2 = namedtuple('NameB2','value')
NameC = namedtuple('NameC','index')
NameC_value = NameC(78)
NameB2_value = NameB2(76)
NameB_value = NameB(6, NameB2_value)
NameA_value = NameA(5,NameB_value,NameC_value)
TopTuple_value = TopTuple(NameA_value)
return TopTuple_value
Now you can access NameA with: indexmodbus.NameA etc.
Within pytorch, creating layers, can be semi automated, thus the reason for using a for loop.
One of the main issues is that these layers cannot stored within a list or dictionary or else back propagation will not work.
Thus the reason for a work around.
Within the object, assigning new self attributes
How do i replace this
self.res1 = 1
self.res2 = 2
self.res3 = 3
with this
for i in range(2):
res_name = 'res'+str(i+1)
self.res_name = i
Now that i have created objects this way, how can I access them in the same way. For example, if we assume self.res_name is now an object?
for i in range(2):
res_name = 'res'+str(i+1)
out = self.res_name(out)
You probably should use a dict or list instead. But if you really want this for some reason, you can try setattr(x, attr, 'magic').
Thus, in your case, it's
for i in range(1, 4):
res_name = 'res' + str(i)
setattr(self, res_name, i)
See this related question for more info.
I want to use a while loop to initialize class objects with a simple incremented naming convention. The goal is to be able to scale the number of class objects at will and have the program generate the names automatically. (ex. h1...h100...h1000...) Each h1,h2,h3... being its own instance.
Here is my first attempt... have been unable to find a good example.
class Korker(object):
def __init__(self,ident,roo):
self.ident = ident
self.roo = roo
b = 1
hwinit = 'h'
hwstart = 0
while b <= 10:
showit = 'h' + str(b)
print(showit) #showit seems to generate just fine as demonstrated by print
str(showit) == Korker("test",2) #this is the line that fails
b += 1
The errors I get range from a string error to a cannot use function type error.... Any help would be greatly appreciated.
If you want to generate a number of objects, why not simply put them in an array / hash where they can be looked up later on:
objects = {}
for b in range(1,11):
objects['h'+str(b)] = Korker("test", 2)
# then access like this:
objects['h3']
Of course there are ways to make the names available locally, but that's not a very good idea unless you know why you need it (via globals() and locals()).
Variables are names that point to objects that hold data. You are attempting to stick data into the variable names. That's the wrong way around.
instead of h1 to h1000, just call the variable h, and make it a list. Then you get h[0] to h[999].
Slightly different solution to viraptor's: use a list.
h = []
for i in range(10):
h.append(Korker("test",2))
In fact, you can even do it on one line with a list comprehension:
h = [Korker("test", 2) for i in range(10)]
Then you can get at them with h[0], h[1] etc.