Access dynamically created class instance variable, Kivy framework - python

Imagine following structure (I've cut most imho relevant parts):
class mymodificatorclass:
def callback(self,object):
print object
class generator(BoxLayout):
#(...)
def add(self, *l):
for i,t in enumerate(self.texts):
self.mytext.append(TextInput(hint_text=t, on_text_validate=modify.callback(self)))
self.add_widget(self.mytext[i])
#(...)
modify = mymodificatorclass() #global scope variable
prints for example <main.generator object at 0x433eef0>. Which is fine.
But, how would one access this class instance variables?
meaning, desired output would be:
print XXXXX
$ <__main__.mytext object at 0x433eef0>
print XXXXX.text, XXXXX
$ "text inside" <__main__.mytext object at 0x433eef0>
I've checked:
print object.__class__.__dict__.items() #no mytext here
print object.mytext #no mytext here
print getattr(object,object.mytext) # object generator has no attribute mytext
I know i can assign for example additional variable storing each TextInput object, but i'd rather not, since i know that if I modified example like this:
class generator(BoxLayout):
def add(self, *l):
for i,t in enumerate(self.texts):
self.mytext.append(TextInput(hint_text=t, on_text_validate=self.callback))
self.add_widget(self.mytext[i])
def callback(self,object):
print object
i would get desired result (i had that like this, but decided i need to move closer to mvc )

self.mytext.append(TextInput(hint_text=t,
on_text_validate=modify.callback(self)))
You are calling the function instead of passing it. Use functools.partial.
self.mytext.append(TextInput(hint_text=t,
on_text_validate=partial(modify.callback, self)))

Related

How to update variables passed between classes?

I'm trying to pass variables between different classes. In order to accompish this task, I have created an info class (here called 'declaration') so that the code reads:
class declaration():
def __init__(self):
self.info1 = 999
self.info2 = 'something_else'
print ('At declaration ')
class controller():
def __init__(self):
instance = declaration()
print ('Initial number ',instance.info1, instance.info2)
modifier(declaration)
print ('MIDDLE ',instance.info1,declaration.info1)
instance = declaration()
print ('Final number ',instance.info1)
class modifier():
def __init__(self,aux):
print ('MODIFIER')
self.info=aux
self.info.info1=55555
controller()
The output is:
At declaration
Initial number 999
something else
MODIFIER
MIDDLE 999 55555
At declaration
Final number 999
However, I'm not really sure about some of the inners of the code. I have one major question and a minor one. My main question is that when the class 'modifier' is modified according to:
class modifier():
def __init__(self,aux):
self.info=aux
print ('MODIFIER',self.info.info1)
self.info.info1=55555
it produces the error AttributeError: type object 'declaration' has no attribute 'info1' [Flipping the last 2 lines fixes the error]. It's confusing (at least to me) whether the class attributes are not passed or they have to be reinitialized.
The second question is how to update instance once its class has been updated. The second call to instance = declaration() seems to accomplish nothing.
Quick side note: Yes I do realise, I just want to say please try to follow the PEP8 python guide as it makes your code look cooler (and easier to read) and all the cool kids use it.
There are a few things wrong with your code, calling modifier(declaration) actually makes the aux parameter an uninitilized class, you want to call modifier(instance) as the init function has already been ran.
Also it would be easier to drop the self.info = aux as you can just call aux.info1 and it looks cleaner and is actually faster (Because you are calling one less Fast Store command in bytecode).
Lastly at print ('MIDDLE ',instance.info1,declaration.info1) you again parse declaration uninitilized therefore you get the error AttributeError: type object 'declaration' has no attribute 'info1', to fix this simply put declaration().info1 as that calls the init function (it is the same as saying declaration.__init__().info1).
So finally you get:
class declaration():
def __init__(self):
self.info1 = 999
self.info2 = 'something_else'
print ('At declaration ')
class controller():
def __init__(self):
instance = declaration()
print ('Initial number ', instance.info1, instance.info2)
modifier(instance)
print ('MIDDLE ', instance.info1, declaration().info1)
instance = declaration()
print ('Final number ',instance.info1)
class modifier():
def __init__(self, aux):
print ('MODIFIER')
aux.info1 = 55555
controller()
Hope this helped.

Something like setter and getter for a python dictionary

I have the following problem:
A class contains a dict of dicts of dicts ... e.g.
class Try():
def __init__(self):
self._tryDict = {'first':{'b':{'bla':'x'},'c':1},'second':{'b':15,'c':1}}
#getter
def tryDict....
#tryDict.setter
def tryDict....
I would like to have now something like setter and getter to change a variable at a certain level of the dict and retrun the corresponding dict a view levels above (and only if i set a new value)
e.g.
try = Try()
try.tryDict['first']['b']['bla']
returs: 'x'
try.tryDict['first']['b']['bla']='z'
changes 'x' to 'z' and returns the content of try.tryDict['first'] ({'b':{'bla':'x'},'c':1})
To understand why I need this:
The dict is actually a list of file-praser-functions and the content is also stored as a dict.
i.e.
dict = {'file-1':dict-1, 'file-1':dict-1, 'file-1':dict-1, ...}
with dict['file-1']['content-3']=1 I set the new content
and with dict['file-1'].write(), the content of the file is updated in the file. The dict is a class instance and I would like to immediately wirte the change to the file.
many thx for your help!
BR, maths
OK so what I implemented it now this way:
Each file got setter and getter function
class dicts():
.....
# to show the content
#getter
def tryDict(self):
return tryDict.file
# to sett some content
#tryDict.setter
def tryDict(self, entry):
if len(entry)==2:
name, newEntry = entry
tryDict.file[name]= newEntry
if len(entry)==3:
....
if i whan to get the entry:
tryDicis = dicts()
tryDicis.trydict # shows the dictionary
i can now set in different levels like:
tryDicis = dicts()
tryDicis.trydict = (name-level-1, name-level-2,..., newEntry)
This is maybe not the most elegant way, however it is easy to implement and good enough in my case.
BR, maths

How do I run two or more methods in a class like a chain?

I'm trying to learn OOP but I'm getting very confused with how I'm supposed to run the methods or return values. In the following code I want to run read_chapters() first, then sendData() with some string content that comes from read_chapters(). Some of the solutions I found did not use __init__ but I want to use it (just to see/learn how i can use them).
How do I run them? Without using __init__, why do you only return 'self'?
import datetime
class PrinceMail:
def __init__(self):
self.date2 = datetime.date(2020, 2, 6)
self.date1 = datetime.date.today()
self.days = (self.date1 - self.date2).days
self.file = 'The_Name.txt'
self.chapter = '' # Not sure if it would be better if i initialize chapter here-
# or if i can just use a normal variable later
def read_chapters(self):
with open(self.file, 'r') as book:
content = book.readlines()
indexes = [x for x in range(len(content)) if 'CHAPTER' in content[x]]
indexes = indexes[self.days:]
heading = content[indexes[0]]
try:
for i in (content[indexes[0]:indexes[1]]):
self.chapter += i # can i use normal var and return that instead?
print(self.chapter)
except IndexError:
for i in (content[indexes[0]:]):
self.chapter += i
print(self.chapter)
return self????? # what am i supposed to return? i want to return chapter
# The print works here but returns nothing.
# sendData has to run after readChapters automatically
def sendData(self):
pass
#i want to get the chapter into this and do something with it
def run(self):
self.read_chapters().sendData()
# I tried this method but it doesn't work for sendData
# Is there anyother way to run the two methods?
obj = PrinceMail()
print(obj.run())
#This is kinda confusing as well
Chaining methods is just a way to shorten this code:
temp = self.read_chapters()
temp.sendData()
So, whatever is returned by read_chapters has to have the method sendData. You should put whatever you want to return in read_chapters in a field of the object itself (aka self) in order to use it after chaining.
First of all, __init__ has nothing to do with what you want to achieve here. You can consider it as a constructor for other languages, this is the first function that is called when you create an object of the class.
Now to answer your question, if I am correct you just want to use the output of read_chapters in sendData. One of the way you can do that is by making the read_chapters a private method (that is if you don't want it to use through the object) using __ in the starting of the name like __read_chapters then make a call to the function inside the sendData function.
Another point to consider here is, when you are using self and don't intend to use the function through the object you don't need to return anything. self assigns the value to the attribute of the current instance. So, you can leave the function read_chapters at self.chapter = i and access the same in sendData.
Ex -
def sendData(self):
print(self.chapter)
I'm not an expert but, the reason to return self is because it is the instance of the class you're working with and that's what allows you to chain methods.
For what you're trying to do, method chaining doesn't seem to be the best approach. You want to sendData() for each iteration of the loop in read_chapters()? (you have self.chapter = i which is always overwritten)
Instead, you can store the chapters in a list and send it after all the processing.
Also, and I don't know if this is a good practice but, you can have a getter to return the data if you want to do something different with (return self.chapter instead of self)
I'd change your code for:
import datetime
class PrinceMail:
def __init__(self):
self.date2 = datetime.date(2020, 2, 6)
self.date1 = datetime.date.today()
self.days = (self.date1 - self.date2).days
self.file = 'The_Name.txt'
self.chapter = []
def read_chapters(self):
with open(self.file, 'r') as book:
content = book.readlines()
indexes = [x for x in range(len(content)) if 'CHAPTER' in content[x]]
indexes = indexes[self.days:]
heading = content[indexes[0]]
try:
for i in (content[indexes[0]:indexes[1]]):
self.chapter.append(i)
except IndexError:
#not shure what you want to do here
for i in (content[indexes[0]:]):
self.chapter.append(i)
return self
# sendData has to run after readChapters automatically
def sendData(self):
pass
#do what ever with self.chapter
def get_raw_chapters(self):
return self.chapter
Also, check PEP 8 Style Guide for naming conventions (https://www.python.org/dev/peps/pep-0008/#function-and-variable-names)
More reading in
Method chaining - why is it a good practice, or not?
What __init__ and self do on Python?

why does python obj.atribute return adress location and obj.atribute.atribute return the value?

To get the value of an attribute I need to call method.attribute.attribute instead of method.attribute, why is this? Calling method.attribute results in a memory address. How should/can I change my code to make method.attribute work?
Most issues regarding this center around calling print(f) instead of print(f())
class MyList:
"""stores a list and does other stuff eventualy"""
this_list = []
def __init__(self, *args):
for arg in args:
self.this_list.append(arg)
def print_list(self):
"""prints the atribute:"description" from the stored objects in the list"""
for x in range(len(self.this_list)):
print(MyClassObj(self.this_list[x]).description, sep="\n")
This is the code that is supposed to print the value of the attribute description
class MyClassObj:
"""test object to be stores in the "MyList" object."""
def __init__(self, description):
self.description = description
This is the object that contains the attribute I want to get.
class CallList:
"""creates the objects, lists and calls the print method"""
#staticmethod
def main():
test1, test2 = MyClassObj("Test1"), MyClassObj("Test2")
list1 = MyList(test1, test2)
list1.print_list()
Main() is called outside the above classes.
The output I get is
<__main__.MyClassObj object at 0x007908F0>
<__main__.MyClassObj object at 0x00790910>
Process finished with exit code 0
If i change line:
print(MyClassObj(self.this_list[x]).description.description, sep="\n")
I get the expected result:
Test1
Test2
Process finished with exit code 0
So the question is why and how should I alter my code?
in print_list self.this_list[x] is already a MyClassObj so MyClassObj(self.this_list[x]) creates a new MyClassObj having a MyClassObj as its description.
Because there is no way defined to convert a MyClassObj to a string for print Python uses a default conversion showing the memory address.

Defining "add" function in a class

I'm writing my own code language in Python (called Bean), and I want the math functions to have the syntax:
print math.add(3+7)
==>10
print math.mul(4*8)
==>32
and so on. So far my code is:
bean_version = "1.0"
console = []
print "Running Bean v%s" % bean_version
#Math Function
class math(object):
def __init__(self, add, sub, mul, div):
self.add = add
self.sub = sub
self.mul = mul
self.div = div
def add(self):
print self.add
math = math(1,0,0,0)
print math.add()
But this will return an error, saying that TypeError: 'int' object is not callable. I can change the "add" function to a different name and it will work, but I would like to use "add" as the name.
Thanks (This is Python 2.7.10 by the way)
An object can't have two properties with the same name. So if you have a property called add that holds a number, it can't also have a method called add, because methods are just properties that happen to hold functions. When you do:
this.add = add
you're replacing the method with that number. So you need to use different names.
You say you want to be able to call math.Add(). But the method you defined is add. It should be:
def Add():
print this.add
This doesn't conflict with the add property that holds the number, since names are case-sensitive.
If you don't want to change the name of the add function, you can just change self.add. These two adds are conflicting with each other. You will not get any error if you run this:
bean_version = "1.0"
console = []
print "Running Bean v%s" % bean_version
#Math Function
class math(object):
def __init__(self, add, sub, mul, div):
self.adds = add
self.sub = sub
self.mul = mul
self.div = div
def add(self):
print self.adds
math = math(1,0,0,0)
print math.add()

Categories

Resources