x-ray
P.S. А насчет клиента - так ведь он реально прав в том случае! Сам предпочитаю работать больше с клавиатурой (быстрее и удобнее), даже немного освоил “слепой” метод. Поэтому не понимаю интерфейсов программ, на которых работают только мышью, очень неудобно! Вот и делаю для себя и друзей оба варианта нажатия на кнопки.
Но это слегка неестественно. Естественней пробел :)
Поехали по вопросу. Давайте разберемся со следующим кодом:
from tkinter import* from ttk import* # root = Tk() but = Button(root, text="push") but.pack() # root.mainloop()
Как Вы думаете, Button чей вообще? Думаете это tkinter. Ан нет. Это ttk. Класс был подменен. При этом Вы об этом узнаете только после воспроизвидения и будете дивится, почему виджет такой красивый :)
А если я хочу только из ttk использовать виджет notebook? Как мне в этом случае быть? Нифига не получится, потому как часть виджетов уже подменена ttk. Все имена, которые совпали с tkinter стали теперь ttk!
Далее. Смотрим следующий код:
from tkinter import* N = 12 # Какая-та нужная, очень нужная константа :) # root = Tk() # Тут очень много строчек кода... but = Button(root, text="push") # Вы забыли, что использовали переменную вверху, так ка уже напедорили 400-600 строк. # И Вы хотите расположить виджет под указанной точкой. but.place(relx=0.5, rely=0.5, anchor=N) root.mainloop()
Вызовет ошибку. Но при импортировании у tkinter есть объект N, который характеризует оносительное рассположение виджета…
Кроме того, давайте глянем, какие имена добавила инструкция в наше пространство имен
from tkinter import* print dir()
['ACTIVE', 'ALL', 'ANCHOR', 'ARC', 'At', 'AtEnd', 'AtInsert', 'AtSelFirst', 'AtSelLast', 'BASELINE', 'BEVEL',
'BOTH', 'BOTTOM', 'BROWSE', 'BUTT', 'BaseWidget', 'BitmapImage', 'BooleanType', 'BooleanVar',
'BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'Button', 'CASCADE', 'CENTER', 'CHAR',
'CHECKBUTTON', 'CHORD', 'COMMAND', 'CURRENT', 'CallWrapper', 'Canvas', 'Checkbutton', 'ClassType',
'CodeType', 'ComplexType', 'DISABLED', 'DOTBOX', 'DictProxyType', 'DictType', 'DictionaryType',
'DoubleVar', 'E', 'END', 'EW', 'EXCEPTION', 'EXTENDED', 'EllipsisType', 'Entry', 'Event', 'FALSE', 'FIRST',
'FLAT', 'FileType', 'FixTk', 'FloatType', 'Frame', 'FrameType', 'FunctionType', 'GROOVE', 'GeneratorType',
'GetSetDescriptorType', 'Grid', 'HIDDEN', 'HORIZONTAL', 'INSERT', 'INSIDE', 'Image', 'InstanceType',
'IntType', 'IntVar', 'LAST', 'LEFT', 'Label', 'LabelFrame', 'LambdaType', 'ListType', 'Listbox', 'LongType',
'MITER', 'MOVETO', 'MULTIPLE', 'MemberDescriptorType', 'Menu', 'Menubutton', 'Message', 'MethodType',
'Misc', 'ModuleType', 'N', 'NE', 'NO', 'NONE', 'NORMAL', 'NS', 'NSEW', 'NUMERIC', 'NW', 'NoDefaultRoot',
'NoneType', 'NotImplementedType', 'OFF', 'ON', 'OUTSIDE', 'ObjectType', 'OptionMenu', 'PAGES', 'PIESLICE',
'PROJECTING', 'Pack', 'PanedWindow', 'PhotoImage', 'Place', 'RADIOBUTTON', 'RAISED', 'READABLE',
'RIDGE', 'RIGHT', 'ROUND', 'Radiobutton', 'S', 'SCROLL', 'SE', 'SEL', 'SEL_FIRST', 'SEL_LAST', 'SEPARATOR',
'SINGLE', 'SOLID', 'SUNKEN', 'SW', 'Scale', 'Scrollbar', 'SliceType', 'Spinbox', 'StringType', 'StringTypes',
'StringVar', 'Studbutton', 'TOP', 'TRUE', 'Tcl', 'TclError', 'TclVersion', 'Text', 'Tk', 'TkVersion', 'Toplevel',
'TracebackType', 'Tributton', 'TupleType', 'TypeType', 'UNDERLINE', 'UNITS', 'UnboundMethodType',
'UnicodeType', 'VERTICAL', 'Variable', 'W', 'WORD', 'WRITABLE', 'Widget', 'Wm', 'X', 'XRangeType', 'XView',
'Y', 'YES', 'YView', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'askopenfilename',
'getboolean', 'getdouble', 'getint', 'image_names', 'image_types', 'mainloop', 'outdirbtn', 'press', 'pyscripter',
'release', 'sys', 'tkinter', 'wantobjects']
Вы уверены, что в других импортированных модуля этих имен нет?
Выводы неутешительные и следующие:
1. from module import* можно использовать только в том случае, когда точно знаешь имена всех объектов модуля, т.е. модуль самопальный или не сильно перегружен.
2. Все имена, которые начинаются с символа “__” (например __silent) не портируются в пространство имен интрукцией from module import* и остануться за бортом. Это нужно помнить. А это дополнительный напряг :)
3. Опасно потрировать модули у которых пространства имен могут пересекаться. Можно только гадать, какая смесь и из чьих объектов в итоге выйдет.
4. После импортирования можно легко заменить один объект пространства имен другим (даже этого не зная) и потом тратить время на поиски и переименования замененного объекта по всему файлу (например, если Вы уже задействовали везде Вашу переменную N, то придется ее везде переименовать в N_, тогда объект, который импортирован из модуля tkinter останется не тронутым).
5. Не всегда можно отличить вызов “самопальной” функции и функции которую Вы портировали. А иногда это бывает необходимо. Выше писал пример про обертку. Там это было нужно…
6. Отладка по ссылкам из пространства имен в этом случае может быть очень мучительна и болезненна.
7. Соответсвенно про простое использование инструкции vars() можно тоже забыть.
Поэтому можно сделать вывод. Никогда так лучше не делать!!!
P.S. Надеюсь желание так писать отбил :)
P.S.S. Кроме того не забываем одно из золотых правил питона: “Явное лучше неявного”…