Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tk menu

1 view
Skip to first unread message

dch

unread,
Nov 21, 2008, 10:09:19 AM11/21/08
to
Witam, szukałem odpowiedzi bez rezultatu, może ktoś z Was będzie znał
rozwiązanie.

Jest sobie lista ttn, która ląduje w menu, sądziłem że select_ttn
wypisze mi wartość, która zostanie wybrana z menu, ale tak się nie
dzieje. Wygląda na to, że za każdym razem po wybraniu z menu wartości,
wywoływana jest funkcja slect_ttn z ostatnio zapamiętanym parametrem.
Jak spowodować, żeby parametr zmieniał się dynamicznie zgodnie z
wybrem z menu? Albo jaką metodą mogę wyciągnąć wskazywaną w menu
wartość?

<code>
from Tkinter import *
ttn = ('A','B','C','D','E','F')

def select_ttn(k):
print k

root = Tk()

menuTblNames = Menubutton(root,text='menu')
menuLstTtn = Menu(menuTblNames)
menuTblNames.config(menu=menuLstTtn)

for i in ttn:
menuLstTtn.add_radiobutton(label=i, command=(lambda: select_ttn
(i)))

menuTblNames.pack()
root.mainloop()
</code>

Rob Wolfe

unread,
Nov 21, 2008, 11:01:43 AM11/21/08
to

dch napisał(a):
> Witam, szukalem odpowiedzi bez rezultatu, moze ktos z Was bedzie znal
> rozwiazanie.
>
> Jest sobie lista ttn, ktora laduje w menu, sadzilem ze select_ttn
> wypisze mi wartosc, ktora zostanie wybrana z menu, ale tak sie nie
> dzieje. Wyglada na to, ze za kazdym razem po wybraniu z menu wartosci,
> wywolywana jest funkcja slect_ttn z ostatnio zapamietanym parametrem.
> Jak spowodowac, zeby parametr zmieniac sie dynamicznie zgodnie z
> wybrem z menu? Albo jaka metoda moge wyciagnac wskazywana w menu
> wartosc?

Musisz pamietac, ze string to w Pythonie obiekt jak kazdy inny
i zawsze poslugujesz sie referencja do niego.

>
> <code>
> from Tkinter import *
> ttn = ('A','B','C','D','E','F')
>
> def select_ttn(k):
> print k
>
> root = Tk()
>
> menuTblNames = Menubutton(root,text='menu')
> menuLstTtn = Menu(menuTblNames)
> menuTblNames.config(menu=menuLstTtn)
>
> for i in ttn:
> menuLstTtn.add_radiobutton(label=i, command=(lambda: select_ttn
> (i)))

Zdefiniowales anonimowa funkcje, ktora korzysta z *referencji* `i`
do obiektu typu `str`. W trakcie obiegu petli *referencja* `i`
wskazuje
na rozne obiekty `str`.
Funkcja anonimowa jest wywolywana po zakonczeniu tej petli,
dopiero w momencie wyboru pozycji menu przez usera.
Na jaki obiekt wskazuje wtedy *referencja* `i`?

>
> menuTblNames.pack()

# dla cwiczenia mozesz sobie tu dopisac

i = 'X'

# i zobaczyc co wyjdzie ;)

> root.mainloop()
> </code>

Przeanalizuj sobie to:

<code>
for i in ttn:
fun1 = lambda: select_ttn('%r (%r)' % (i, id(i)))
fun2 = lambda x=i: select_ttn('%r (%r)' % (x, id(x)))
menuLstTtn.add_radiobutton(label=i, command=fun2)
</code>

RW

Message has been deleted
Message has been deleted

dch

unread,
Nov 21, 2008, 1:16:14 PM11/21/08
to
> i = 'X'
> #   i zobaczyc co wyjdzie ;)
to już wcześniej ćwiczyłem, niestety zawiele mi to nie pomogło,
pomyślałem wtedy, że funkcja jest wywoływana zawsze z ostatnim
"zapamiętanym" parametrem i utknąłem.

> <code>
> for i in ttn:
>    fun1 = lambda: select_ttn('%r (%r)' % (i, id(i)))

to wiadomo, będzie działać tak jak powyższym przykładzie

>    fun2 = lambda x=i: select_ttn('%r (%r)' % (x, id(x)))

a to jest niezwykłe, oczywiście działa i zupełnie tego nie rozumiem :-
p

do obiektu fun2 przypisane jest wywołanie funkcji select_ttn, która z
kolei korzysta z referencji do obiektu x, który korzysta z referencji
do obiektu i, a ponieważ wywołanie tej funkcji również następuje
dopiero po wykonaniu pętli, dlatego wydaje się, że x powinien odnosić
się, tak samo jak w przypadku fun1, do 'F' (po wykonaniu pętli obiekt
i wskazuje na 'F'), a jednak tak nie jest. Że tak się zapytam, czy to
magia?

>    menuLstTtn.add_radiobutton(label=i, command=fun2)

dziękuję za odpowiedź!

Rob Wolfe

unread,
Nov 21, 2008, 2:26:14 PM11/21/08
to
dch <dhc...@gmail.com> writes:

>> i = 'X'
>> #   i zobaczyc co wyjdzie ;)
> to już wcześniej ćwiczyłem, niestety zawiele mi to nie pomogło,
> pomyślałem wtedy, że funkcja jest wywoływana zawsze z ostatnim
> "zapamiętanym" parametrem i utknąłem.
>
>> <code>
>> for i in ttn:
>>    fun1 = lambda: select_ttn('%r (%r)' % (i, id(i)))
> to wiadomo, będzie działać tak jak powyższym przykładzie
>
>>    fun2 = lambda x=i: select_ttn('%r (%r)' % (x, id(x)))
> a to jest niezwykłe, oczywiście działa i zupełnie tego nie rozumiem :-
> p
>
> do obiektu fun2 przypisane jest wywołanie funkcji select_ttn, która z

Stop!
Do `fun2` jest przypisane wywołanie anonimowej (nienazwanej) funkcji,
bo do tego służy `lambda` [1]_.
Czyli to jest definicja funkcji anonimowej:

>>> fun1 = lambda: "fun1"
>>> fun1()
'fun1'
>>> fun2 = lambda x: "fun2: %r" % x
>>> fun2('A')
"fun2: 'A'"


a to nazwanej:

>>> def fun1(): return "fun1"
...
>>> fun1()
'fun1'

Funkcja `select_ttn` jest wywoływana wewnątrz funkcji anonimowej
dopiero po wywołaniu tejże anonimowej funkcji.

> kolei korzysta z referencji do obiektu x, który korzysta z referencji
> do obiektu i, a ponieważ wywołanie tej funkcji również następuje
> dopiero po wykonaniu pętli, dlatego wydaje się, że x powinien odnosić
> się, tak samo jak w przypadku fun1, do 'F' (po wykonaniu pętli obiekt
> i wskazuje na 'F'), a jednak tak nie jest. Że tak się zapytam, czy to
> magia?

Różnica polega na tym, że `fun2` przyjmuje domyślny parametr wejściowy.
Wartość takiego parametru jest ustalana tylko raz (w momencie defincji
funkcji). Zauważ, że `fun1` nie przyjmuje żadnego parametru wejściwoego.
Twój problem sprowadza się do tego:

>>> i = 'A'
>>> def f():
... print i
...
>>> def g(x=i):
... print x
...
>>> f()
A
>>> g()
A
>>> i = 'F'
>>> f()
F
>>> g()
A

Funckja `f` cały czas korzysta ze zmiennej `i`. Cokolwiek do niej
przypiszesz, to wyśiwetli funkcja `f`.
Funkcja `g` korzysta ze zmiennej *lokalnej* `x`, która tylko raz
(podczas definicji funkcji `g`) jest zainicjalizowana. Zostanie
do niej przypisane aktualne wskazanie referencji `i` i to się
już później nie ma prawa zmienić.

.. [1] http://docs.python.org/reference/expressions.html#id17

RW

dch

unread,
Nov 24, 2008, 4:10:42 AM11/24/08
to

> Funckja `f` cały czas korzysta ze zmiennej `i`. Cokolwiek do niej
> przypiszesz, to wyśiwetli funkcja `f`.
> Funkcja `g` korzysta ze zmiennej *lokalnej* `x`, która tylko raz
> (podczas definicji funkcji `g`) jest zainicjalizowana. Zostanie
> do niej przypisane aktualne wskazanie referencji `i` i to się
> już później nie ma prawa zmienić.
>
> .. [1]http://docs.python.org/reference/expressions.html#id17

dzięki za wyjaśnienie,

dch

0 new messages