How to get object name of the widget in focus? - python-3.x

Very similiar to
print("focus object class:", window2.focus_get().__class__)
taken from here:
Python get focused entry name
, but I need the exact name of the object.
Something like: self.entrywidget_1
OR:
What to fill the place holder to make if true ?
print(self.focus_get().__class__)
if self.focus_get().__class__ == "placeholder":
print("I work")
The first print returns < class 'tkinter.Entry' >

You can't. Any given object can have many names. For example, given the following code, which name would you expect to get?
self.foo = tk.Button(...)
self.bar = self.foo
You rarely, if ever, need the name of the widget. Having a reference to the widget -- like that is returned by focus_get() -- is all you need. With that yo can insert data, delete data, destroy the widget, get the widget contents, etc.
If you really do need some predictable, unique identifier in the case where the same function must work for multiple widgets, you can give each widget a custom attribute that is a symbolic name. You can then get that name at runtime. For example:
e = tk.Entry(...)
e.name = "placeholder"
...
focused_widget = root.focus_get()
print (the name of the focused widget is %s" % focused_widget.name)
Again, you likely won't ever need that. For example, if you want to delete the text in the focused widget, just use the reference to the widget:
focused_widget.delete(0, "end")
If all you really need is to check if the focused widget is a specific widget, just do a direct comparison:
...
self.placeholder = tk.Entry(...)
...
def whatever(self):
focused_widget = root.focus_get()
if focused_widget == self.placeholder:
print("I work")

Related

Python copies/duplicates object rather than instantiates a default one

First off, I'm relatively new to Python, so pardon the rough code I have. Here goes: I have a class with a constructor. It inherits a few properties from a superclass. This same class can also be a child object of itself. So an Epic can hold an Epic, which I'm appending to the Children property as a list.
class Epic(V1Superclass):
Type = 'Epic'
Children = []
ParentAssetID = []
#classmethod
def __init__(self, **kwargs):
for key, value in kwargs.items():
if key == 'Name':
self.Name = value
elif key == 'Description':
self.Description = value
elif key == 'Super':
self.Super = value
elif key == 'Scope':
self.Scope = value
if not bool(self.Super):
self.Super = None
if not bool(self.Scope):
self.Scope = 445082
def populateChildren(self,env,key):
children = V1.utl.getChildren(env,key,'Epic',self.AssetID)
for child in children:
if child['_oid'].split(':')[0] == 'Story':
print('Got another backlog child')
elif child['_oid'].split(':')[0] == 'Defect':
print('Got another Defect child')
elif child['_oid'].split(':')[0] == 'Epic':
childEpic = V1.Epic()
self.Children.append(childEpic)
If I create two instances of this class in the python console, everything's fine. I do "a = V1.Epic()" and "b = V1.Epic()", and the world is good. They all initialize to the proper default values (or empty). However, when I run my code in the populateChildren function, when I instantiate a new Epic object, rather than create a default version of the Epic, it is creating a new instance, but with all the properties of the parent (self) object. In essence, it's an exact copy, but if I do a "self is childEpic" command, it returns false, which (if I understand things correctly) means that childEpic is not a copy of the parent object. I can manipulate the child object and set properties with no problem, but obviously that's not how this should work. This is kind of maddening, as I'm not even sure what to google to see what I'm doing wrong syntax wise.
TIA!
I've tried adding an addChild function which tries to instantiate an instance outside the scope of the parent object, but even within that function, the object created is a duplicate of the parent
Your __init__ function is defined as a class method, which means that its first parameter is not a reference to the instance of the new object, but instead a reference to the current class. These properties are present on each of the class's instances, so it appears that they are being copied over.
Remove the #classmethod decorator from the __init__ function and the self parameter will refer to the object being instantiated.

Can anyone explain me about __init_ in Python?

List item
class Car:
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.number_of_wheels = 4
self.registration_number = GenerateRegistrationNumber()
Hi all,
1)Referring to the above example, could anyone tell me what is the difference between specific attributed and "the other" attributes? What will happen if registration_number is treated as a specific attribute?
2)
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
If we consider this example, shouldn't it be self.newvalue = newvalue?
I think I know what you're asking (let me know if I'm wrong), but I think you're asking what the difference is between the attributes that are assigned by the parameters of __init__ (Instance Attributes), ones that are assigned inside the __init__ method but not with parameters (also Instance Attributes), and ones that are not assigned in the initialiser at all (Class Attributes). The difference here is that all (well, pretty much all) cars have 4 wheels, and the number plate is generated, not supplied. You could also do this, for example:
class Car:
number_of_wheels = 4
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.registration_number = GenerateRegistrationNumber()
As the number of wheels here is always assigned to the same value, across all instances, it is said to be a "Class Attribute" in this case. All other attributes here are “Instance Attributes” as they are specifically assigned to each instance. For a slightly better explanation, I recommend reading this:
https://www.geeksforgeeks.org/class-instance-attributes-python/
It doesn't actually matter what the instance attribute (self.value here) is called, you could call it whatever you want and it'd still work, but in most cases, you would indeed want to name the attribute the same as the parameter.
init function also called as magic function is a constructor function for a class. if you remember in java whenever we make a class the constructor method should have the same name as the classname but this is not the scenario in python . In python we make use of the init method
the difference between the class attributes and instance attributes is that the class attributes are common to every object that is created but the instance attributes are only accessible by the object that is created.
consider a example where data of students in a class is stored. In such case the class division will be same for all the students of that particular class so it can be common but names of all students are different and also their marks and so on and hence they should be different for everyone
in previous scenario the class division can be class attribute and the data of student like name , marks has to be instance attributes
examples of class attribute is as shown
class A:
Division = 5A
here the division is a class attribute
class B:
def __init__(self,name,marks):
self.name = name
self.marks = marks
here the name and marks are instance variables
now here we can also write self.username = name because we are storing the value of name variable in self.username so you can write any name there is no constraint on that
Also whenever you write __ in front of method or variable it means that the attribute is private and accessible by only class.

How can I make objects with functions? (Turning a string into a object name)

I've just started learning Python recently and the first project I'm making is a text based adventure game however I've run into a problem. I need a function that makes more objects using the class Goblin that are named after a string.
def spawn(name):
title = name
exec("{0} = {1}".format('title', Goblin))
return title, 'spawn'
Essentially, another function calls this function to create another Goblin (a class) using the input name(a string) as the name of the new Goblin.
What I don't under stand though is that when I run the code(using "bill" as the argument), it gives me this error.
bill = <class '__main__.Goblin'>
^
SyntaxError: invalid syntax
Shouldn't my function be equivalent to:
bill = Goblin
When you do this:
exec("{0} = {1}".format('title', Goblin))
format method converts Goblin class by calling default __str__ method which yields <class '__main__.Goblin'>
Do this instead:
exec("{0} = {1}".format('title', 'Goblin'))
Wait! don't to this, just do:
title = Goblin
as it's strictly equivalent (without any security issues :)).
But that will just alias Goblin class to title. No real interest to all this after all (unless you want to create an instance?: title = Goblin())
With your comment: "I want a Goblin that is named after the string which title represents" I get it: you need
exec("{0} = {1}".format(title, 'Goblin()'))
(no quotes for the first arg so the name you're passing is used, and () on the second to create an instance)
Again: this is really a clumsy way of doing it. What if you want to iterate through all your goblins?
It would be much better to create a dictionary:
goblins_dict = dict()
goblins_dict["my_goblin"] = Goblin()
goblins_dict["my_goblin_2"] = Goblin()
and so on...

Passing StringVar object from Entry to Label within functions in tkinter

Hi I've been struggling to get this to work, each time i change something I receive another error. I've been trying to create an entry box with a function and then get the variable from the entry box into a label, created by a button press. When I tried to do this often this error came up.
TypeError: get() missing 1 required positional argument: 'self'
I then put self in in the method brackets.
command = lambda: x.myFunc(self.my_variable.get(self))
Then another error, which I'm not sure how to sort out.
AttributeError: 'My_Class' object has no attribute '_tk'
Here's the full code, I'm new to classes and self, so any corrections are welcome.
from tkinter import *
import time
class My_Class:
def start(self):
self.root=Tk()
self.my_variable=StringVar
self.entry_box=Entry(self.root, textvariable=self.my_variable)
self.entry_box.pack()
self.button=Button(self.root,text="Pass variable now",
command=lambda:x.myFunc(self.my_variable.get(self)))
self.button.pack()
def myFunc(self,my_variable):
self.lab=Label(self.root,text=self.my_variable)
self.lab.pack()
x=My_Class()
x.start()
This is the correct way to create a StringVar object:
text = StringVar() # note additional ()
Can you explain me what x is in the following statement:
lambda: x.myFunc(self.my_variable.get(self))
x is not visible inside the class, because it's declared outside the class.
myFunc is not indented correctly: you should indent it like the __init__ method.
I really recommend you to watch some tutorials on OOP before proceeding. You are basically trying to guess how OOP works.
If you make myFunc A method if the class (which you might be trying to do; it's hard to know because your indentation is wrong), you don't have to pass anything to myFunc. That function has access to everything in the class, so it can get what it needs, when it needs it. That lets you eliminate the use of lambda, which helps reduce complexity.
Also, you normally don't need a StringVar at all, it's just one more thing to keep track of. However, if you really need the label and entry to show exactly the same data, have them share the same textvariable and the text is updated automatically without you having to call a function, or get the value from the widget, or set the value n the label.
Here's an example without using StringVar:
class My_Class:
def start(self):
...
self.entry_box = Entry(self.root)
self.button = Button(..., command = self.myFunc)
...
def myFunc(self):
s = self.entry_box.get()
self.lab = Label(..., text = s)
...

Access element of list by variable name

How can I access a list element using the name of the list?
I would like to allow a user to edit the code in determine a single variable to be inputted into a function. For example:
blah = [1,2]
blah2 = 5
toBeChanged = "blah2"
def foo():
print(blah)
def changeVariable():
globals()[toBeChanged] += 1
for time in range(5):
changeVariable()
simulate
This works for blah2 since it is a simple variable, however it will not work for blah[0] since it is part of a list. I've also tried placing my variables into a dictionary as other answers have suggested, but I still am unable to change list elements through a simple string.
Is there a way to do this that I am missing? Thanks!
Rather than using globals() and altering directly it would be much, much better to use a dictionary to store the variables you want the user to alter, and then manipulate that:
my_variables = {
'blah': [1,2]
'blah2': 5
}
toBeChanged = "blah2"
def foo():
print(my_variables['blah'])
def changeVariable():
my_variables[toBeChanged] = my_variables.get(toBeChanged,0) + 1
for time in range(5):
changeVariable()
This has the added advantage that if a user enters a variable that doesn't exist a default is chosen, and doesn't override any variables that might be important for future execution.

Resources