I'm trying to work on a simple class that fills in some lists and then tries to retrieve that information back, something like:
class Foo(object):
def __init__(self):
self.src = []
self.values = []
def addItems(self, name, val):
self.src.append(name)
self.values.append(val)
def getItem(self, item):
for i, x in enumerate(self.src):
if x == item:
return self.src[i], self.values[i]
To use this class, I first have to instanciate it, Foo(), and only then start adding and retrieving objects.
a = Foo()
a.addItems('A', '1')
a.addItems('B', '2')
a.src # ['A', 'B']
a.values # ['1', '2']
a.getItem('A') # ('A', '1')
Is there any way to add the elements without having to initialise the class first? Something like Foo.addItems('A', '1')(this gives a TypeError: addItems() missing 1 required positional argument: 'val').
I saw other related posts using #staticmethod, but couldn't figure out how to make it work in this example.
Not sure what exactly you have in mind. I guess you may get something close to what you have described. Two steps are needed.
First - create module, say, foo_module, where you create and instantiate your class:
class Foo:
def __init__(self):
self.src = []
self.values = []
def addItems(self, name, val):
self.src.append(name)
self.values.append(val)
def getItem(self, item):
for i, x in enumerate(self.src):
if x == item:
return self.src[i], self.values[i]
root_foo = Foo()
src = root_foo.src
values = root_foo.values
def addItems(*args):
return root_foo.addItems(*args)
def getItem(*args):
return root_foo.getItem(*args)
Second - import foo_module and use it:
import foo_module as f_m
f_m.addItems('A', '1')
f_m.addItems('B', '2')
print(f_m.getItem('A'))
print(f_m.src)
print(f_m.values)
Now you access the same Foo instance any time you access foo_module across all your scripts. By the way, it's how python logging module works (root logger).
Related
Given:
class NoName:
def __init__(self):
self.some_dict = {}
def add_new_node(self, label):
self.some_dict[label] = {}
Consider I call the class how would I use the add_new_node method ? what prams will I need to pass in the add_new_node method ?
NoName.add_new_node('a':1)
obviously, this will not work. I need to understand how to make such positional arguments work.
It's this what you are looking for?
class NoName:
def __init__(self):
self.some_dict = {}
def add_new_pair_key_value(self, node, value):
self.some_dict[node] = value
def add_new_whole_node(self, whole_node):
self.some_dict.update(whole_node)
noname = NoName()
noname.add_new_pair_key_value('new_node', 'new_value')
print(noname.some_dict)
noname.add_new_whole_node({'label': {'new_whole_key': 'new_node_value'}})
print(noname.some_dict)
output first print:
{'new_node': 'new_value'}
output second print:
{'new_node': 'new_value', 'label': {'new_whole_key': 'new_node_value'}}
I'm need to read different datasets, and all of them have some equal properties (e.g. ID and name) and some unique properties. I know that I can build a different function to read each dataset, but I was wondering if it is possible to build a generic dataset reader if I use something like this
My class:
def MyClass():
def __init(self):
self.default_prop1 = ''
self.default_prop2 = ''
My main file:
def main():
keys = ['default_prop1', 'default_prop2', 'not_default_prop1', 'not_default_prop2' ]
obj_myclass = MyClass()
for i in keys:
#Here
obj_myclass[i] = file.readline()
Is there a way to do something like this?
I'll update your class a little bit:
def Car(): #an example of a car class
def __init(self, props):
self.props = ({}, {})
Now you can iterate over the default properties and the extra ones:
def main()
new_car = Car(({"year": 1998}, {"sports_car_type": "countach"}))
# Now, you can go through the keys in both dictionaries of this new object
print("defaults:")
for key, val in new_car.props[0].items():
print(key, val)
print("~~~~~~~~~\extras:")
for key, val in new_car.props[1].items():
print(key, val)
main()
You can use the vars() mechanism. Fixing two typos in your sample code, to give
class MyClass(): # not def
def __init__(self): # not __init
self.default_prop1 = ''
self.default_prop2 = ''
you can do
>>> mc = MyClass()
>>> vars(mc)
{'default_prop1': '', 'default_prop2': ''}
The object returned by vars() is a proper dict (it returns the __dict__ attribute) and can be updated the way you want.
>>> vars(mc)["new_prop"] = "Fred"
>>> mc.new_prop
'Fred'
Or, if you want to do it in a loop:
>>> for i in (v := vars(mc)):
v[i] = file.readline()
I am writing a class where I would like to pass function as a class attribute and later use it, like that:
class Nevronska_mreza:
def __init__(self, st_vhodni, st_skriti, st_izhod, prenosna_funkcija=pf.sigmoid):
self.mreza = []
self.st_vhodni = st_vhodni
self.st_skriti = st_skriti
self.st_izhodni = st_izhod
self.prenosna_funckija = prenosna_funkcija
self.mreza.append([{'utezi': [random() for i in range(st_vhodni + 1)]} for j in range(st_skriti)])
self.mreza.append([{'utezi': [random() for i in range(st_skriti + 1)]} for j in range(st_izhod)])
def razsirjanje_naprej(self, vhod):
for sloj in self.mreza:
nov_vhod = []
for nevron in sloj:
nevron['izhod'] = self.prenosna_funkcija(self.aktivacijska_funkcija(nevron['utezi'], vhod))
nov_vhod.append(nevron['izhod'])
vhod = nov_vhod
return vhod
but it seems like this isn't the right way, I get the following error:
AttributeError: 'Nevronska_mreza' object has no attribute 'prenosna_funkcija'
Is it possible to do something like that?
Yes you can pass a function around as an argument however you have made a couple of mistakes.
Firstly you have used the word function, although not a reserved word it should be avoided as a name of an entity such as a variable.
Secordly you have used an optional parameter before mandatory parameters which will cause an error such as:
File "test.py", line 5
def __init__(self, function=fun1, data1, data2):
^
SyntaxError: non-default argument follows default argument
Thirdly when calling the method you have not specified the scope, the function name is in the self scope of the object.
Taking all of these into account the following is working code
def fun1(x):
return x+1
class A:
def __init__(self, data1, data2, fn=fun1):
self.fn = fn
self.data1 = data1
self.data2 = data2
def some_method(self):
y = self.fn(self.data1)
print(y)
b = A(1, 2, fun1)
b.some_method()
After posting your full code I can see that you currently have self.prenosna_funckija instead of prenosna_funkcija in the following line:
self.prenosna_funckija = prenosna_funkcija
This would explain the attribute error as when you are calling self.prenosna_funkcija it genuinely does not exist.
You're close:
def fun1(x):
return x+1
class A:
def __init__(self, function=fun1, data1=None, data2=None):
self.function = function
self.data1 = data1
self.data2 = data2
def some_method(self):
y = self.function(self.data1)
return y
a = A(data1 = 41)
result = a.some_method()
print(result)
prints
42
Assume I have two classes that use threads
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
def run(self):
while True
value, name = getvalue() // name is an string
self.var1[name] = value
bar(self)
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
def run(self):
while True
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
f = foo()
f.start()
The variable var1 in foo will change over time and bar needs to be aware of these changes. It makes sense to me, but I wonder if there is something fundamental here that could fail eventually. is this correct in python?
The actual sharing part is the same question as "how do I share a value with another object?" without threads, and all the same solutions will work.
For example. you're already passing the foo instance into the bar initializer, so just get it from there:
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
But is this thread-safe?
Well, yes, but only because you never actually start the background thread. But I assume in your real code, you're going to have two threads running at the same time, both accessing that var1 value. In which case it's not thread-safe without some kind of synchronization. For example:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.var1lock = threading.Lock()
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
self.var1lock = fooInstance.var1lock
And now, instead of this:
self.var1[name] = value
… you do this:
with self.var1lock:
self.var1[name] = value
And likewise, instead of this:
val = myOtherfunction(fooInstance.var1[arg]) //other function
… you do this:
with self.var1lock:
var1arg = var1[arg]
val = myOtherfunction(var1arg)
Or… as it turns out, in CPython, updating a value for a single key in a dict (only a builtin dict, not a subclass or custom mapping class!) has always been atomic, and probably always will be. If you want to rely on that fact, you can. But I'd only do that if the lock turned out to be a significant performance issue. And I'd comment every use of it to make it clear, too.
If you'd rather pass values instead of share them, the usual answer is queue.Queue or one of its relatives.
But this requires a redesign of your program. For example, maybe you want to pass each new/changed key-value pair over the queue. That would go something like this:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.q = queue.Queue()
def run(self):
b = bar(self)
b.start()
while True:
value, name = getvalue() // name is an string
self.var1[name] = value
self.q.put((name, value))
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = copy.deepcopy(fooInstance.var1)
self.q = fooInstance.q
def _checkq(self):
while True:
try:
key, val = self.q.get_nowait()
except queue.Empty:
break
else:
self.var1[key] = val
def run(self):
while True:
self._checkq()
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
I built a class to handle a lot of different functions that take common inputs. However, I just ran into the situation where one of the variables that's fed down through self needs to be changed. How do I do this? This is an example:
class Test:
def __init__(self, test_variable):
self.test_var = test_variable
#property
def some_function(self):
if self.test_var < 0:
self.test_var = 'New Output' #this is the line that I can't get
#get to work and I was hoping to update it here
#so I could use it in later functions
return self.test_var
Thank you!
You should drop the #property attribute. Then, you can set it by just doing x.test_var = 5. E.g.,
class Test:
def __init__(self, test_variable):
self.test_var = test_variable
def some_function(self):
if self.test_var < 0:
self.test_var = 'New Output' #this is the line that I can't get
#get to work and I was hoping to update it here
#so I could use it in later functions
return self.test_var
x = Test(-1)
print(x.some_function())
x.test_var = 5
print(x.some_function())
returns
New Output
5