I have a number of objects with a similar name format, e.g. max_A, max_B, max_C etc. Given the value of a certain object ID, I'd like to change the value of the object named max_ID (let's say increment by 1, assuming the object already stores an int).
E.g. if ID = 'A' then I'd like to execute max_A += 1, but if ID = 'Q' then I'd like max_Q += 1.
I know I can use eval('max_'+ID) to get the value of max_ID, but how can I change the value?
You can represent the objects like bellow and use endswith function to find the appropriate object to be incremented:
class Data:
def __init__(self, name, value):
self.name = name
self.value = value
max_A = Data("max_A", 1)
max_B = Data("max_B", 2)
max_C = Data("max_C", 3)
obj_list = [max_A, max_B, max_C]
def increment_object_value(ending: str, objects: list):
for obj in objects:
if obj.name.endswith(ending):
obj.value += 1
increment_object_value("A", obj_list)
increment_object_value("B", obj_list)
increment_object_value("C", obj_list)
Related
I have a function that returns an array and a second function that is supposed to use this returned array, but the program returns saying array is not defined. How can I fix this problem?
def popt_reader(filename):
with codecs.open(popt, 'r', encoding='utf-8') as data_file:
rows, cols = [int(c) for c in data_file.readline().split() if c.isnumeric()]
array = np.fromstring(data_file.read(), sep=' ').reshape(rows, cols)
return array
def cleaner():
out = []
en_point = 0
for i in range(1,len(array)):
if np.all((array[i,1::] == 0)):
pass
else:
out.append(array[i,:])
en_point += 1
print(en_point)
cleaner(array)
You never call the function that returns the array. Try this, just input your own file name
...
filename = "my_array_file_here.array"
array = popt_reader(filename)
cleaner(array)
Variable array is defined within the popt_reader function and is not accessible within the cleaner function.
Add this line of code before cleaner(array) to make it work:
array = popt_reader(filename)
Which will assign output of popt_reader method to array variable.
Note that filename should also be defined beforehand
filename = "path to file"
Just add a signature(parameter) to the function cleaner()
second one should be:
def cleaner(array):
out = []
en_point = 0
for i in range(1,len(array)):
if np.all((array[i,1::] == 0)):
pass
else:
out.append(array[i,:])
en_point += 1
print(en_point)
cleaner(array)
I know that return is like throwing out a value at the end of an operation and that it actually stops the iteration or the function in which it's residing. I am having this very simple piece of code where classmethods & class variables are used.
class Person:
number_of_people = 0
def __init__(self, name):
#Person.number_of_people +=1
Person.add_person()
#classmethod
def get_person_count(cls):
return cls.number_of_people
#classmethod
def add_person(cls):
# return cls.number_of_people+1 <-- this does not work. Output is 0 and 0. Why?
cls.number_of_people += 1 #<-- this works
P1 = Person("Rups")
print(P1.get_person_count())
P2 = Person("RG")
print(P2.get_person_count())
As I have commented on the lines, why is my method giving output 0 both times and not the expected output(1 & 2), which is achieved using plan variable modification? Either way, I thought I should be able to use the value given out by add_person method in the init method, since there is no looping involved.
Returning a value does not mean it is modifying a variable. It just means that something can use what is returned. The difference is that cls.number_of_people += 1 changes number_of_people to it's value + 1 (due to the = sign), while return cls.number_of_people+1 takes number_of_people + 1 and "throws" it for something else to use.
What this means is that if add_person returns a value, anytime you call add_person(), there is a value that can be used.
# {...}
def add_person(cls):
return cls.number_of_people + 1
P1 = Person("Rups")
print(P1.add_person()) # prints 1 (number_of_people which is 0, then add 1)
print(P1.add_person()) # still prints 1
I know this is a noob question but I am learning OOPs and can't able to figure the outputs got
This is the code I found and may i know how this runs?
class InstanceCounter(object):
count = 0
def __init__(self, val):
self.val = val
InstanceCounter.count += 1
def set_val(self, newval):
self.val = newval
def get_val(self):
print(self.val)
def get_count(self):
print(InstanceCounter.count)
a = InstanceCounter(5)
b = InstanceCounter(10)
c = InstanceCounter(15)
for obj in (a, b, c):
print("value of obj: %s" % obj.get_val())
print("Count : %s" % obj.get_count())
You have a class called InstanceCounter which inherits from object. The inherince from object can be removed if you use Python3. This class has an attribute count and value and some methods (functions - for example set_val).
Now you create three objects of your class and set the value of value to 5, 10 and 15 by passing these values into the constructor. You also increase the static attribute (see here) count by one with each constructor call. A static attribute is used with the notation Class.Attribute.
In the last step you loop over a list of your three objects ((a, b, c)) and store each of this object in the object obj, so obj will represent a then b and then c. So you can call the methods of this object, because your object obj has the type InstanceCounter and so obj contain the same methods and attributes.
By the way I have reworked your code so make it more understandable and use Python3 syntax.
class InstanceCounter:
count = 0
def __init__(self, val):
self.val = val
InstanceCounter.count += 1
def set_val(self, newval):
self.val = newval
def get_val(self):
return self.val
def get_count(self):
return InstanceCounter.count
a = InstanceCounter(5)
print("Count : {}".format(a.get_count()))
b = InstanceCounter(10)
print("Count : {}".format(b.get_count()))
c = InstanceCounter(15)
print("Count : {}".format(c.get_count()))
for obj in (a, b, c):
print("value of obj: {}".format(obj.get_val()))
print("Count : {}".format(obj.get_count()))
This result in the following output:
Count : 1
Count : 2
Count : 3
value of obj: 5
Count : 3
value of obj: 10
Count : 3
value of obj: 15
Count : 3
For a better understanding of static attributes:
So if you have three objects with type InstanceCounter you have three different attributes with name val because each object with type InstanceCounter contains one attribute val - an instance attribute and one identical attribute with name count - a class attribute.
count is a class attribute for the class InstanceCounter. This
attribute has the same value for all objects with type
InstanceCounter. Used with Classname.Attributename - for example InstanceCounter.count.
val is a instance attribute because each instance of a class InstanceCounter has his own value. Used with Instancename.Attributename - for example a.val.
See here for more information.
I'm doing a Python 3 based data conversion and certain character based fields I operate on have specific character allowances and length constraints applied to them.
I'd want to have some sort of swappable/configurable constraint function I roll myself that I could call.
Can you extend str?
Is it best to define a class for this and make variables implementations of that class.
Or are there simpler ways to do this with Python 3?
I'm wondering if anyone can give me pointers as to what to Google for inspiration?
(My initial thoughts are to look at SQLAlchemy's internal code for inspiration for things like Column).
EDIT: SQLAlchemy's code is too sophisticated for this scenario!
For example a type that only allows:
alphanumerics (upper+lowercase)
numerics
plus a selection of special characters.
This may vary by field, but some may use same function.
Hence desire to create custom re-usable types.
I'll do character stripping or substitution.
Then one may only allow 50 chars, whilst another may allow 500 etc.
I'll pass back a tuple with original value, converted value, a boolean to indicate truncation occurred
This is what I ended up with:
valobj.py
import utils
class UDT:
def __init__(self, converter, maxlen, value):
if utils.getClassName(converter) != 'function':
raise TypeError(f'converter {converter} is not a function')
if int(maxlen) <= 0:
raise TypeError(f'maxlen {maxlen} must be 1 or more')
if utils.getClassName(value) != 'str':
raise TypeError(f'value {value} is not a Python String')
self.converter = converter
self.maxlen = int(maxlen)
self.value = value
def convert(self):
intermed = self.converter(self.value)
truncated = len(intermed) > self.maxlen
result = intermed[:self.maxlen] if truncated else intermed
return (result, truncated, self.value)
class Job:
def __init__(self, name):
self._name_tuple = UDT(utils.fix_chars, 64, name).convert()
utils.py
import string
def getClassName(arg):
return(str(type(arg)).replace("<class '","").replace("'>",""))
def fix_chars(text) -> str:
result = ''
for c in text:
if ( (string.ascii_letters.find(c) != -1)
or (string.digits.find(c) != -1)
or ('._-#'.find(c) != -1)
):
result += c
else:
result += '_'
result = tidy_up_str(result)
return (result)
def tidy_up_str(text) -> str:
result = text
result = result.replace('_-_', '_')
while result.find('__') != -1:
result = result.replace('__', '_')
if result.endswith('_'):
result = result[:-1]
return result
n = 3
d = {'x':n}
d['x'] += 1
print(n)
When I run it, I get
3
How do I make n = 4?
You can't do this, at least, not in any simple way.
The issue is very similar when you're just dealing with two variables bound to the same object. If you rebind one of them with an assignment, you will not see the new value through the other variable:
a = 3
b = a
a += 1 # binds a to a new integer, 4, since integers are immutable
print(b) # prints 3, not 4
One exception is if you are not binding a new value to the variable, but instead modifying a mutable object in-place. For instance, if instead of 1 you has a one-element list [1], you could replace the single value without creating a new list:
a = [3]
b = a
a[0] += 1 # doesn't rebind a, just mutates the list it points to
print(b[0]) # prints 4, since b still points to the same list as a
So, for your dictionary example you could take a similar approach and have n and your dictionary value be a list or other container object that you modify in-place.
Alternatively, you could store the variable name "n" in your dictionary and then rather than replacing it in your other code, you could use for a lookup in the globals dict:
n = 3
d = {"x": "n"} # note, the dictionary value is the string "n", not the variable n's value
globals()[d["x"]] += 1
print(n) # this actually does print 4, as you wanted
This is very awkward, of course, and only works when n is a global variable (you can't use the nominally equivalent call to locals in a function, as modifying the dictionary returned by locals doesn't change the local variables). I would not recommend this approach, but I wanted to show it can be done, if only badly.
You could use a class to contain the data values to enable additions. Basically you are creating a mutable object which acts as an integer.
It is a work around, but lets you accomplish what you want.
Note, that you probably need to override a few more Python operators to get full coverage:
class MyInt(object):
val = 0
def __init__(self,val):
self.val = val
def __iadd__(self,val):
self.val = self.val + val
def __repr__(self):
return repr(self.val)
n = MyInt(3)
print(n)
d = {'x':n}
d['x'] += 1
print(n)