Define a dictionary during its first update, is this possible ?

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
Post Reply
Snowbird
Experienced User
Posts: 283
Joined: Fri Jul 03, 2009 10:04 am

Define a dictionary during its first update, is this possible ?

Post by Snowbird » Mon Apr 16, 2018 8:03 am

Hi all,
I'm wondering if there is a better way or a shorter way to do this :

Code: Select all

try:
  MyDict
except NameError:
  MyDict = {}

MyDict[Var1] = {Var2: Var3}
eg.globals.MyDict = MyDict
1/ is there a way to define a dictionary upon its first update of key:value ?
2/ why can't I use a global variable from the start ? it gives me an error... to overcome this, I must first use a regular variable, do all the work with it and then define the global variable at the end.

Sorry if my questions are silly or make no sense, I'm not very good at python (I could almost say I'm bad :p)

Thank you, please don't just give me the right answer, if you could explain a bit so I can understand my mistakes and learn from them ;)

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Mon Apr 16, 2018 9:28 am

ok. so this is how the python scripts work.

If the script gets run any variables you set in it the first time will get carried over to the second time you run it. and since there is no real way of knowing if it has been run before other then duck typing or asking if the variable is there.

example of duck typing

Code: Select all


try:
    mydict
except NameError:
    mydict = {}
asking if it exists

Code: Select all


if 'mydict' not in locals():
    mydict = {}
    

Now some say it is easier to ask for forgiveness then to ask for permission. But in this example they are close to being the same. The biggest difference is that exception catching is very expensive. meaning it slows down your code.

in your example you only need to set the dict to eg.globals a single time. the reason why is python dictionaries are mutable. I will explain through code

Code: Select all

if 'mydict' not in locals():
    mydict = {}
    eg.globals.mydict = mydict

mydict['key'] = 'value'

print eg.globals.mydict['key']

Now you look at this and say.. how does this work?!?!? well whatever changes you make to mydict are also going to be made to the "copy" in eg.globals. it really isn't a copy it is still the same dictionary. eg.globals.mydict is a memory pointer to mydict so any changes you make to eg.globals.mydict will also be available in mydict.

python lists also act the same way. where a tuple () is not mutable. hence the reason why you cannnot do item assignment with a tuple.

this will fail.

Code: Select all

tuple_test = (1, 2, 3, 4, 5)
tuple_test[0] = 0
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Mon Apr 16, 2018 9:34 am

and you can define a global right out of the gate if you want

Code: Select all

eg.globals.mydict = getattr(eg.globals, 'mydict', {})
the getattr is used to get an attribute. so we want to get the attribute mydict from eg.globals. and the {} on the end is if the attribute does not exist. the reason for setting it back to eg.globals.mydict is so that is it exists then it will stay the same and if it does not it will create it.

I guess you can also do something similar for locals as well

Code: Select all

mydict = locals().get('mydict', {})
I do not remember if it is locals or globals that gets saved from scripts. but in the event i have them backwards then change out the locals for globals

Code: Select all

mydict = globals().get('mydict', {})
If you like the work I have been doing then feel free to Image

Snowbird
Experienced User
Posts: 283
Joined: Fri Jul 03, 2009 10:04 am

Re: Define a dictionary during its first update, is this possible ?

Post by Snowbird » Mon Apr 16, 2018 1:40 pm

Kevin to the rescue :)

ok, I have understood everything in your first post, the thing that helped a better understanding is when you stated that global variables are in fact pointers to local variables, this I didn't know, and it's a detail that makes a huge difference in the comprehension ! thanks !

Regarding your second post, to be honest with you I didn't understand very well how the getattr really works, I think I need to read more about it.

But anyway, because of you I learned interesting and useful things today !! :)

Thank you again, you're the best! ;)

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Mon Apr 16, 2018 4:18 pm

nope i didn't say that global variables are pointers to locals.

i said that mutable variables can have pointers to it.


It is very difficult to explain this in a manner that is not going to confuse the hell out of ya because of the use of the term "globals"

as an example in a python script if you do the following you can only read from the variable you cannot set the variable.

Code: Select all

TEST = 'This is a local variable'

def test_func():
    print TEST

def set_test():
    TEST = 'This will not work, This is creating another local variable but a variable that is local to "set_test"'

def global_set_test():
    global TEST

    TEST = 'This is a global variable'


test_func()
set_test()
test_func()

TEST = 'This is resetting the local variable'

test_func()
global_set_test()
test_func()
so when i say globals i do not mean eg.globals.
eg.globals is a container that can be accessed from anywhere in EventGhost. but this is because "eg" has been added to the python builtin commands. same thing as calling str() or int() you do not have to import those. "eg" has been placed into the same mechanics that allow str() or int() or dict() to work.


you can state

Code: Select all

TEST = 'this will only be global to the script it is running in'
globals TEST
and it will never be accessible anywhere else except for in that script
If you like the work I have been doing then feel free to Image

Snowbird
Experienced User
Posts: 283
Joined: Fri Jul 03, 2009 10:04 am

Re: Define a dictionary during its first update, is this possible ?

Post by Snowbird » Mon Apr 16, 2018 5:07 pm

ok, I think I got it this time. I was thinking that the statement "global" and "eg.globals" were doing the same thing :) in fact "global" is used to set/read a variable anywhere in the script even inside functions (as opposed to local where each variable is controlled in its own space), and "eg.globals" is to use a variable anywhere in EG (this part I already knew it).

So when you were talking about pointers, you were being specific to "eg.globals.var" pointing to "var" no matter if "var" was a local or a global variable as long as it has been assigned somewhere in the script that "eg.globals.var = var".

so to sum up what I have understood :
local : set/read in its own space where it was created
global : set/read anywhere in the script, even inside functions
eg.globals : set/read from anywhere in EG, in any script and/or function

Am I correct ? (I hope so LOL)

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Mon Apr 16, 2018 5:48 pm

very very very close.


global is only global to the space where it was declared global in


so in the next 3 code snippits the first one will not work. Because the global was not set in the same namespace where the TEST variable gets reset.
The second does work.
and the 3rd is an oddity because in order to have the global available to the sub function you have to declare the global first. then set it and then redeclare it as a global in the sub functions namespace

Code: Select all


TEST = None

def some_func():
    global TEST

    def run_func():
        TEST = 'This is a test'

    run_func()

some_func()
print TEST

Code: Select all





TEST = None


def some_func():

    def run_func():
        global TEST

        TEST = 'This is a test'

    run_func()


some_func()

print TEST

Code: Select all

def some_func():
    global TEST

    TEST = None

    def run_func():
        global TEST

        TEST = 'This is a new test'

    run_func()

    print TEST


some_func()


there are 2 name spaces defined for each "level". a general idea of how levels can be arranged is

Code: Select all

module
    class
        method
            function
                class... and so on and so forth
    function
        function
        class
            method... and so on and so forth
but a good rule of thumb is if you see "def" or "class" then a new level has begun and does not end until code restarts at the same indent level as the "def" or "class" was keyed on.


Again you can read from anything that is on a lower level but you cannot write to it unless it is declared a global. Now this is going to appear as writing information for in fact it is not.

Code: Select all


some_list = []

def write_list():
    some_list.append('new data')
    
write_list()
print some_list()

you are actually reading a method called "append" from some_list and passing your data to it. and it is writing the data.

This code below does exactly the same thing as above but will fail. because you are writing the data directly. in order for this to work you would have to declare a global

Code: Select all


some_list = []

def write_list():
    some_list += ['new data']
    
write_list()
print some_list()

the 2 name spaces are locals and globals. now when dealing with classes they have given you an easy mechanism to "share" variables between methods without the need to be globals all over the place. and this is the self mechanism. the self mechanism gives access to variables that get stored in the class.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Mon Apr 16, 2018 5:56 pm

I know this is really hard to wrap your noggin around. My bean is throbbing just typing this out. and I think I am having flashbacks of when i was trying to understand this. and I didn't have anyone to explain it to me. So if you need me to give a poke at it again but maybe describing it differently I can give it a shot. I know that for one person it being described this way they will understand but another may not. and simply changing it up or giving another set of examples will do the trick for the second person.

I give the code examples to explain what is happening in each and why, also so you an run them and see the output.
If you like the work I have been doing then feel free to Image

Snowbird
Experienced User
Posts: 283
Joined: Fri Jul 03, 2009 10:04 am

Re: Define a dictionary during its first update, is this possible ?

Post by Snowbird » Thu Apr 19, 2018 7:23 am

thanks for this in-depth explanation, it's still a bit fuzzy in my head but I'm about to understand this, I need to reread a couple of times and do some tests to definitely get it ! I'm sooooo close :p

Thanks again for your time and patience, it's rare to see people with this much passion ;)

User avatar
kgschlosser
Site Admin
Posts: 3595
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Define a dictionary during its first update, is this possible ?

Post by kgschlosser » Thu Apr 19, 2018 11:02 pm

No worries m8. I enjoy helping people out. If there is a specific thing you are stuck on, let me know and I will be more then happy to help ya out.
If you like the work I have been doing then feel free to Image

Post Reply