Append/Write with values of an instance - python

So I'm new to working with classes in python, but this project Euler(q 81) I have is done using classes just to be a bit more tricky? I guess?
I can get the values of a (2n+1 * 2n+1) grid, but I can't work with them to append to another list or even write to a file.
def minSum(matrix):
file = open("pleasedeargodwork.txt", "w")
newList = []
for x in maxtrix.grids:
for y in x:
newList.append(y)
print y,
file.write(y,)
print newList
>>> 1 7 2 5 6 2 9 2 5
>>> TypeError: must be string or read-only character buffer, not instance
>>> <matrix.Supplies instance at 0x0240E9B8>
^^ I would like this last line to give me the values, rather than the instance, but how?
My matrix class looks something like this:
class Matrix:
def __init__(self, grids):
self.size = len(grids) / 2
self.grids = [[Supplies(s) for s in row] for row in grids]
class Supplies:
def __init__(self, supp):
if isinstance(supp, list):
self.value = supp[0]
"Matrix" is the class name, "matrix" is the filename and an argument given to my class minSum to be able to access this file.
If you need to see any more of the matrix file let me know.
Thanks.

Looks like you have another error when you try to write an instance to the text file but here's a way to print the values instead of the instance:
The __repr__ method lets you define what the object looks like when it is printed.
Add a __repr__ method to the Supplies class like so:
class Supplies:
def __init__(self, supp):
if isinstance(supp, list):
self.value = supp[0]
def __repr__(self):
return str(self.value)
Whenever you print a Supplies instance, Python will print its value attribute instead. Note that value is not guaranteed to be defined in the Supplies class so you might want to either initialize it or check before you attempt to convert it to a string in the __repr__ method.
Edit
If you want newList to contain the values of each Supplies instance you could just append the value instead of the instance:
newList.append(y.value)
instead of:
newList.append(y)

Related

Python return value prints only one value from the object instead of all the values

I have a Python file with two class A and B, and I am inheriting temp from class A to B. In my class A function temp, I am getting the id value from an XML file which has values like this,
[1,2,3,4,5]
My Class A with temp function
class A:
def temp(self):
id = []
for child in root:
temp_id=child.get('id')
id.append(temp_id)
return id
and I am getting the function value in class B,
class B (A):
fun=A
value = fun.temp()
for x in value:
return x
While printing the return value instead of printing all the values, I am getting only the first value
[1,1,1,1,1]
Can some one please let me know on how to solve this, thanks.
Standard functions can only return a single value. After that, execution continues from where that function was called. So, you're trying to loop through all the values, but return upon seeing the first value, then the function exits and the loop is broken.
In your case, you could simply return fun.temp(). Or, if you want to process each value, then return the new list, you could run something like:
new_list = []
value = fun.temp()
for x in value:
# do something with x here
new_list.append(x)
return new_list
Also, it appears you may be a bit confused about how inheritance works. DigitalOcean has a great article on it, if you want to take a look.

Python - Using list of strings as class data member. When strings contain variables, variables don't update

Is there a way to change variables within lists within classes after the class instance has been initialized? (Sorry, sounds more complicated than it is!)
I'm writing a game and storing all of my display text as array elements in instances of a "Text" class. I wrote the following example program to test what I'm trying to do:
#****************************************#
#INITIALIZE CLASS (to hold text component)
#****************************************#
class Text:
def __init__(self, array, maxIndex):
#list of text
self.list = array
#number of items in list
self.max = maxIndex
#set global variable to 7
globalv = 7
#****************************************#
#INITIALIZE VARIABLE-ENHANCED TEXT
#necessary because variables inside class
#data member arrays seem to have a local
#scope, and can't be changed after they
#are initialized
#****************************************#
varLine = Text(["This line contains globalv, which holds: {}".format(globalv)], 0)
print varLine.list[varLine.max]
#prints 7
#CHANGE VALUE OF globalv:
print "Directly accessing globalv: {}".format(globalv)
#prints 7
print "\nUpdate value of globalv to 9"
globalv = 9
print "Directly accessing globalv: {}".format(globalv)
#prints 9
#Try to change and re-print variable
#doesn't work, despite the fact that "global" has changed outside of the class
print "\nfirst try:"
#call print function on globalv directly:
print "Directly accessing globalv: {}".format(globalv)
#prints 9
#print it from the class:
print "Printing from class:"
print varLine.list[varLine.max])
#prints 7
#Change variable by re-initializing class
print "\nsecond try:"
varLine = Text(["This line contains globalv, which holds: {}".format(globalv)], 0)
#call print function on globalv directly:
print "Directly accessing globalv: {}".format(globalv)
#prints 9
#print it from the class:
print "Printing from class:"
print varLine.list[varLine.max])
#prints 9
When you create that string you are concatinating the current value of globalv into a string. Changing globalv after that string been created has no effect on the value of the string. You can make setter and print methods to accomplish this:
class Text:
def __init__(self, strList, valueList, maxIndex):
#list of text/values
self.strList = strList
self.valueList = valueList
#number of items in list
self.max = maxIndex
def printStrAtIndex(self, idx):
print(self.strList[idx] + str(self.valueList[idx]))
def setValAtIndex(self, val, idx):
self.valueList[idx] = val
return self
# add new str value pair to the the class
def addStrAndValue(self, newStr, newValue):
self.strList.append(newStr)
self.valueList.append(newValue)
self.max = len(self.valueList)-1
Then just call it like this:
varLine = Text(["This line is tied to the value: "], [7], 0)
varLine.printStrAtIndex(0)
varLine.setValAtIndex(9,0)
varLine.printStrAtIndex(0)
Answer is easy.
str.format()
Function returns copy of string with intrerpolated values.
So Your Class contains :
vaeLine.list = ["Copy of formating string with resolved value"]
When You change global var to soemthing this string isn't reevaluated
And this string copy is immutable so Your class is holding array which is muteable but its holding just an already resolved string with value 7. So changing global doesnt affect this stirng.
The code is working correctly. I'm not sure what you're expecting.
You convert globalv to text and store it in an object's text. When you come back later, that text string is just as you left it. Are you expecting it to magically change because you changed the value of globalv? This is somewhat like taking a photograph of yourself, changing clothes, and expecting the photo to change to match your new outfit. Variables don't work that way.
Perhaps what you need is a two-step approach:
Create an attribute to hold the value, such as self.value
Write a method to display an object's attribute; within that method, acces the current value of self.value, using that in the display string that you build.
Does that help?

iterate over an instance object's attributes in Python

I have a class
class MyClass():
def __init__(self):
self.a = 7
self.b = 2
#property
def aAndB(self):
return self.a + self.b
I would like a function that iterates over all properties and returns only class instances having a certain property.
My goal is a function like this:
def findInstances(listOfInstances, instanceVariable, instanceValue):
#return all instances in listOfInstances where instanceVariable==instanceValue
Using instance.__dict__ only gives me a and b, but not aAndB. I would like to have a dict of all properties/methods with their values to loop over, so I can search for instances where a certain property (or method decorated with #property) has a certain value.
Currently, calling the function like this
findInstances(someListOfInstances, 'aAndB', '23')
makes Python complain that aAndB is not in instance.__dict__.
Maybe all of you are right and the answers are there, but I still don't get it. All the answers in the mentioned questions get lists, not dictionaries. I want all the properties (including methods with the #property decorator) and their values. Is there a way to iterate over the values of the keys in dir(myClass)? The dir command only contains the names of the attributes, not their values.
I need something like
for a in dir(myClass):
print a, myClass.(a) # get the value for an attribute stored in a variable
To be even more clear: The following achieves exactly what I want but there is probably a better way that I don't know.
for a in dir(myClass):
print a, eval("myClass.{}".format(a))
There's actually a very simple way to do this, using getattr in place of eval:
myClass = MyClass()
for a in dir(myClass):
if(a[:2] != "__"): #don't print double underscore methods
print a, getattr(myClass, a)
Output:
a 7
aAndB 9
b 2
This has the very big advantage of not needing to hard code in the name of your instance into the string, as is required using eval("myClass.{}".format(a))

How can I use the value of a variable in the name of another without using a dictionary in python?

The answer people have already given for using the value of a variable in the assignment of another is:
to create a dictionary and,
use dict[oldVariable] instead of defining a new one
I don't think that works in the context of what I'm trying to do...
I'm trying to define a class for a vector which would take a list as an input and assign an entry in the vector for each element of the list.
My code looks something like this right now:
class vector:
def __init__(self, entries):
for dim in range(len(entries)):
for entry in entries:
self.dim = entry #here I want to assign self.1, self.2, etc all the way to however
#many elements are in entries, but I can't replace self.dim with
# dict[dim]
def __str__(self):
string = []
for entry in range(1,4):
string.append(self.entry)
print(string)
How do I do this?
What you are doing here is a bit strange, since you are using a variable named "dim" in a for, but you do not do anything with that variable. It looks like you want to use a class as if it was an array... why don't you define an array within the class and access it from the outside with the index? v.elements[1] ... and so on?
Example:
class Vector:
def __init__(self, entries):
self.elements = []
for e in entries:
self.elements.append(self.process(e))
def __str__(self):
buff = ''
for e in self.elements:
buff += str(e)
return buff
Hope this helps.
If I'm reading your question correctly, I think you're looking for the setattr function (https://docs.python.org/2/library/functions.html#setattr).
If you wanted to name the fields with a particular string value, you could just do this:
class vector:
def __init__(self, entries):
for dim in range(len(entries)):
for entry in entries:
#self.dim = entry
setattr(self, str(dict[dim]), dim)
That will result in your object self having attributes named with whatever the values of dict[dim] are and values equal to the dim.
That being said, be aware that an integer value is generally a poor attribute name. You won't be able to do print obj.1 without error. You'd have to do getattr(obj,'1').
I agree with #Ricardo that you are going about this strangely and you should probably rethink how you're structuring this class, but I wanted to directly answer the question in case others land here looking for how to do dynamic naming.

Choosing variables to create when initializing classes

I have a class which would be a container for a number of variables of different types. The collection is finite and not very large so I didn't use a dictionary. Is there a way to automate, or shorten the creation of variables based on whether or not they are requested (specified as True/False) in the constructor?
Here is what I have for example:
class test:
def __init__(self,a=False,b=False,c=False):
if a: self.a = {}
if b: self.b = 34
if c: self.c = "generic string"
For any of a,b,c that are true in the constructor they will be created in the object.
I have a collection of standard variables (a,b,c,d..) that some objects will have and some objects won't. The number of combinations is too large to create separate classes, but the number of variables isn't enough to have a dictionary for them in each class.
Is there any way in python to do something like this:
class test:
def __init__(self,*args):
default_values = {a:{},b:34,c:"generic string"}
for item in args:
if item: self.arg = default_values[arg]
Maybe there is a whole other way to do this?
EDIT:
To clarify this a class which represents different type of bounding boxes on a 2D surface. Depending on the function of the box it can have any of frame coordinates, internal cross coordinates, id, population statistics (attached to that box), and some other cached values for easy calculation.
I don't want to have each object as a dictionary because there are methods attached to it which allow it to export and modify its internal data and interact with other objects of the same type (similar to how strings interact with + - .join, etc.). I also don't want to have a dictionary inside each object because the call to that variable is inelegant:
print foo.info["a"]
versus
print foo.a
Thanks to ballsdotball I've come up with a solution:
class test:
def __init__(self, a=False, b=False,c =False):
default_values = {"a":{},"b":34,"c":"generic string"}
for k, v in default_values.iteritems():
if eval(k): setattr(self,k,v)
Maybe something like:
def __init__(self,*args,**kwargs):
default_values = {a:{},b:34,c:"generic string"}
for k,v in kwargs.iteritems():
try:
if not v is False:
setattr(self,k,default_values[k])
except Exception, e:
print "Argument has no default value.",e
But to be honest I would just put the default values in with the init arguments instead of having to test for them like that.
*Edited a couple times for syntax.
You can subclass dict (if you aren't using positional arguments):
class Test(dict):
def your_method(self):
return self['foo'] * 4
You can also override __getattr__ and __setattr__ if the self['foo'] syntax bothers you:
class Test(dict):
def __getattr__(self, key):
return dict.__getattr__(self, key)
def __setattr__(self, key, value):
return dict.__getattr__(self, key, value)
def your_method(self):
return self.foo * 4

Categories

Resources