How to write GUI application in python one-liner
i wrote this article drinking ebisu red-label beer*1 and tanqueray no10*2. i suppose there are typos and mistakes. if you want more rich commentary, plz comment.
in japanese or 日本語.
qiita.com
python one-liner base theory
statement and expression
the statement
require '\n', so you should use the expression
in one-liner.
you can write almost all process in expression. only try: catch:
statement can't be written in expression.(if you have some idea, plz tell me)
exec()
? it is not cool.
semicolon? it's ugly.
you should learn short-circuit evaluation and implicit coversion.
if condition: A else: B
condition and A or B
if you want to chain process, you should consider A
return.
A B C
A;B;C
# useful in golf, but ugly....
A or B or C # it's sooooo cooooool. # A and B should return False # if B returns True, ... A or not B or C # if return of B is uncertain. # 0 is useful in golf. A or (B and 0) or C
how write assignment in one-liner?
assignment is statement, so you should find same meaning expression.
7. Simple statements — Python 3.4.4 documentation
use build-in globals()
function.
2. Built-in Functions — Python 3.4.4 documentation
in one-liner, all variable is in global scope, because local()
is read-only.
you should define assign lambda function with globals()
, like this.
2. Built-in Functions — Python 3.4.4 documentation
globals().update({'assign': lambda k,v:globals().update({k:v})})
assign
is lambda function with side effect. cool.
import in one-liner
use build-in function: __import__()
[https://docs.python.org/3.4/library/functions.html?highlight=globals#import:title]
sys=__import__('sys') # i always define utility lambda function like follows. assign('i',lambda n:__import__(n)) assign('sys',i('sys'))
python one-liner application theory
dynamic class definition
type()
function enable to create class dynamically, and inherit parent classes.
2. Built-in Functions — Python 3.4.4 documentation
pythonic ex code.
class Gui(tk.Frame): def __init__(self, parent=None): self.parent = parent
in one-liner,
Gui = type('Gui', (tk.Frame), {'__init__': lambda self, parent=None: self.__setattr__('parent', parent)})
learn special methods, modules, build-in functions.
instance and class have useful special methods; __setattr__
, __getattr__
or __dict__
. modules; itertools
, functools
, operator
. build-in functions: map
, all
, sorted
, sum
.
if you want to flatten list, sum
's argument is sum(iter[, start])
, so sum([[1,2],[3],[4,5]],[])
will work.
https://docs.python.org/3.4/library/functions.html?highlight=globals#sum
gui application
write in standard python
i use wallpaperchanger script which i wrote. publishing code in github
(i think this code is not pythonic. i wrote this in beginner... i bother to refactor this code... but ONELINIZE!)
require pillow or PIL for previewing images.
encode with those techniques
WallpaperChanger/clean_wallpaperchanger.py at oneliner · cocuh/WallpaperChanger · GitHub
#!/usr/bin/env python c=lambda k,v:globals().update({k:v}) i=lambda n:c(n,__import__(n)) i('os') i('sys') i('subprocess') i('shlex') i('argparse') i('random') i('itertools') c('CONFIG_PATH',os.path.expanduser('~/.config/wallpaperchanger.conf')) (sys.version_info.major==2 and( c('configparser',__import__('ConfigParser'))or c('tk',__import__('Tkinter'))or c('next',lambda o:o.next()) )or( i('configparser')or c('tk',__import__('tkinter')) )) i('PIL')or i('PIL.Image')or i("PIL.ImageTk") # TODO c("WallpaperChanger",type('WallpaperChanger',(), { '__doc__':"main class\n\n this contains filenames, config.\n", '__init__':lambda s:s.__dict__.update({'wrap_config':WrapConfig()})or s.wrap_config.load()or s.__dict__.update({'config':s.wrap_config.config,'base_path':os.path.expanduser(s.wrap_config.config.get('Main', 'path'))}), 'call':lambda s,fn,ia=False:subprocess.call([l.format(file=fn if ia else os.path.join(s.base_path, fn))for l in shlex.split(s.config.get('Main','command'))])==0and(s.config.set('Wallpaper', 'current', fn)or s.wrap_config.write()), 'get_filenames': lambda s:sorted(os.listdir(s.base_path)), 'get_abspath': lambda s,fn:os.path.join(s.base_path, fn), } )) c("WrapConfig",type("WrapConfig",(),{ "__doc__":"""\nWrap ConfigParser,\n""", "DEFAULT":{'Main':{'path':'~/picture/wallpaper','command':'feh --bg-fill {file}',},'Wallpaper':{'current':'','default':'',}}, "__init__":lambda s:s.__dict__.update({"config":configparser.ConfigParser()})or None, 'load':lambda s:s.is_exists()and (s.config.read(CONFIG_PATH)and None)or(s.set_default()or s.write()), 'write':lambda s:(s.is_exists_parent_directory()or os.makedirs(s._get_parent_path())or True)and(lambda fp:(s.config.write(fp)and None)or fp.close())(open(CONFIG_PATH, 'w')), 'set_default':lambda s,ow=False:[(s.config.has_section(sec)or s.config.add_section(sec))and[(ow or not s.config.has_option(sec, opt)and s.config.set(sec,option,s.DEFAULT[sec][opt]))for opt in s.DEFAULT.get(sec, {}).keys()]for sec in s.DEFAULT.keys()]and None, 'is_exists_parent_directory':lambda s:os.path.isdir(s._get_parent_path()), 'is_exists':lambda s:os.path.exists(CONFIG_PATH), '_get_parent_path':lambda s:os.path.abspath(os.path.dirname(CONFIG_PATH)), })) c("Gui",type("Gui",(tk.Frame,),{ '__doc__':'\nGraphical interface for wallpaper selecting.\n', 'THUMBNAIL_SIZE':(400, 400), '__init__':lambda s,master,ch: s.__dict__.update({'_changer':ch,'filename':None,'key':''})or tk.Frame.__init__(s, master)or s.pack()or s.create_widgets()or s.init_binds()or s.set_listbox_filenames()or s.set_thumbnail(), 'create_widgets':lambda s:(lambda fl:fl.pack({'fill': tk.BOTH, 'side': 'left'})or s.__dict__.update({'elem_listbox':tk.Listbox(fl),'elem_entry':tk.Entry(fl,textvariable=s.gen_entry_callback())}))(tk.Frame(s))or s.elem_listbox.pack({'side': 'top', 'fill': tk.BOTH})or s.elem_entry.pack({'side': 'bottom'})or s.elem_entry.focus_set()or PIL is None or(lambda fr:fr.pack({'fill': tk.BOTH})or s.__dict__.update({'elem_thumbnail':tk.Label(fr)}) or s.elem_thumbnail.pack({'side': 'right',}))(tk.Frame(s))or None, 'init_binds':lambda s:s.master.bind('<Escape>', s.action_destroy)and s.master.bind('<Return>', s.action_finish)and s.master.bind('<Tab>', s.action_completion)and s.elem_listbox.bind('<<ListboxSelect>>', s.action_select)and s.elem_listbox.bind('<Double-Button-1>', s.action_finish)and None, 'action_destroy':lambda s,*args:s.master.destroy(), 'action_select':lambda s,e=None:(e and s.__dict__.update({'filename':s.elem_listbox.get(int(s.elem_listbox.curselection()[0]))})or s.set_thumbnail(s.filename))or None, 'action_finish':lambda s,*args:(s.filename and s._changer.call(s.filename)or s.action_destroy()), 'action_completion':lambda s,*args:(lambda names:(lambda idx:idx and (s.elem_entry.delete(0, tk.END)or s.elem_entry.insert(0, names[0][:idx])and None))(next(itertools.dropwhile(lambda idx:not all(names[0][:idx]in l for l in names[1:]),(len(names[0])-x for x in range(len(names[0])))),None)))(s.get_filtered_filenames(s.key))or 'break', 'gen_entry_callback':lambda s:(lambda string_var:string_var.trace('w', lambda name, index, mode, sv=string_var: (lambda sv:(lambda names:s.set_listbox_filenames(names)or len(names)==1 and(s.__dict__.update({'filename':names[0]})or s.set_thumbnail(names[0])or True)or(s.__dict__.update({'filename':None})or s.set_thumbnail()))(s.__dict__.update({'key':sv.get()})or s.get_filtered_filenames(s.key)))(sv))and None or string_var)(tk.StringVar()), 'set_listbox_filenames':lambda s,fn=None:[s.elem_listbox.insert(tk.END, n)for n in s.elem_listbox.delete(0,s.elem_listbox.size()-1)or(fn and fn or s._changer.get_filenames())]+[1]and None, 'set_thumbnail':lambda s,fn=None:(not PIL or(lambda thumbnail:((fn and (lambda img:img.thumbnail(s.THUMBNAIL_SIZE,PIL.Image.ANTIALIAS)or thumbnail.paste(img,(int(max((s.THUMBNAIL_SIZE[0]-img.size[0])/2, 0)),int(max((s.THUMBNAIL_SIZE[1]-img.size[1])/2,0)))))(PIL.Image.open(s._changer.get_abspath(fn))))and None)or s.__dict__.update({'thumbnail':PIL.ImageTk.PhotoImage(thumbnail)})or s.elem_thumbnail.configure(image=s.thumbnail))(PIL.Image.new('RGBA', s.THUMBNAIL_SIZE, (0, 0, 0, 0)))or True)and None, 'get_filtered_filenames':lambda s,kw:[x for x in s._changer.get_filenames() if x.find(kw) == 0] })) Gui(tk.Tk(), WallpaperChanger()).mainloop()
check returning False and replace '\n' to 'or'.
WallpaperChanger/wallpaperchanger.py at oneliner · cocuh/WallpaperChanger · GitHub
globals().update({'c':lambda k,v:globals().update({k:v})})or c('i',lambda n:c(n,__import__(n)))or i('os')or i('sys')or i('subprocess')or i('shlex')or i('argparse')or i('random')or i('itertools')or c('CONFIG_PATH',os.path.expanduser('~/.config/wallpaperchanger.conf'))or (sys.version_info.major==2 and(c('configparser',__import__('ConfigParser'))or c('tk',__import__('Tkinter'))or c('next',lambda o:o.next()))or(i('configparser')or c('tk',__import__('tkinter'))))or i('PIL')or i('PIL.Image')or i("PIL.ImageTk")or c("WallpaperChanger",type('WallpaperChanger',(),{'__doc__':"main class\n\n this contains filenames, config.\n",'__init__':lambda s:s.__dict__.update({'wrap_config':WrapConfig()})or s.wrap_config.load()or s.__dict__.update({'config':s.wrap_config.config,'base_path':os.path.expanduser(s.wrap_config.config.get('Main', 'path'))}),'call':lambda s,fn,ia=False:subprocess.call([l.format(file=fn if ia else os.path.join(s.base_path, fn))for l in shlex.split(s.config.get('Main','command'))])==0 and(s.config.set('Wallpaper', 'current', fn)or s.wrap_config.write()),'get_filenames': lambda s:sorted(os.listdir(s.base_path)),'get_abspath': lambda s,fn:os.path.join(s.base_path, fn),}))or c("WrapConfig",type("WrapConfig",(),{"__doc__":"""\nWrap ConfigParser,\n""","DEFAULT":{'Main':{'path':'~/picture/wallpaper','command':'feh --bg-fill {file}',},'Wallpaper':{'current':'','default':'',}},"__init__":lambda s:s.__dict__.update({"config":configparser.ConfigParser()})or None,'load':lambda s:s.is_exists()and (s.config.read(CONFIG_PATH)and None)or(s.set_default()or s.write()),'write':lambda s:(s.is_exists_parent_directory()or os.makedirs(s._get_parent_path())or True)and(lambda fp:(s.config.write(fp)and None)or fp.close())(open(CONFIG_PATH, 'w')),'set_default':lambda s,ow=False:[(s.config.has_section(sec)or s.config.add_section(sec))and[(ow or not s.config.has_option(sec, opt)and s.config.set(sec,option,s.DEFAULT[sec][opt]))for opt in s.DEFAULT.get(sec, {}).keys()]for sec in s.DEFAULT.keys()]and None,'is_exists_parent_directory':lambda s:os.path.isdir(s._get_parent_path()),'is_exists':lambda s:os.path.exists(CONFIG_PATH),'_get_parent_path':lambda s:os.path.abspath(os.path.dirname(CONFIG_PATH))}))or c("Gui",type("Gui",(tk.Frame,),{'__doc__':'\nGraphical interface for wallpaper selecting.\n','THUMBNAIL_SIZE':(400, 400),'__init__':lambda s,master,ch: s.__dict__.update({'_changer':ch,'filename':None,'key':''})or tk.Frame.__init__(s, master)or s.pack()or s.create_widgets()or s.init_binds()or s.set_listbox_filenames()or s.set_thumbnail(),'create_widgets':lambda s:(lambda fl:fl.pack({'fill': tk.BOTH, 'side': 'left'})or s.__dict__.update({'elem_listbox':tk.Listbox(fl),'elem_entry':tk.Entry(fl,textvariable=s.gen_entry_callback())}))(tk.Frame(s))or s.elem_listbox.pack({'side': 'top', 'fill': tk.BOTH})or s.elem_entry.pack({'side': 'bottom'})or s.elem_entry.focus_set()or PIL is None or(lambda fr:fr.pack({'fill': tk.BOTH})or s.__dict__.update({'elem_thumbnail':tk.Label(fr)}) or s.elem_thumbnail.pack({'side': 'right',}))(tk.Frame(s))or None,'init_binds':lambda s:s.master.bind('<Escape>', s.action_destroy)and s.master.bind('<Return>', s.action_finish)and s.master.bind('<Tab>', s.action_completion)and s.elem_listbox.bind('<<ListboxSelect>>', s.action_select)and s.elem_listbox.bind('<Double-Button-1>', s.action_finish)and None,'action_destroy':lambda s,*args:s.master.destroy(),'action_select':lambda s,e=None:(e and s.__dict__.update({'filename':s.elem_listbox.get(int(s.elem_listbox.curselection()[0]))})or s.set_thumbnail(s.filename))or None,'action_finish':lambda s,*args:(s.filename and s._changer.call(s.filename)or s.action_destroy()),'action_completion':lambda s,*args:(lambda names:(lambda idx:idx and (s.elem_entry.delete(0, tk.END)or s.elem_entry.insert(0, names[0][:idx])and None))(next(itertools.dropwhile(lambda idx:not all(names[0][:idx]in l for l in names[1:]),(len(names[0])-x for x in range(len(names[0])))),None)))(s.get_filtered_filenames(s.key))or 'break','gen_entry_callback':lambda s:(lambda string_var:string_var.trace('w', lambda name, index, mode, sv=string_var: (lambda sv:(lambda names:s.set_listbox_filenames(names)or len(names)==1 and(s.__dict__.update({'filename':names[0]})or s.set_thumbnail(names[0])or True)or(s.__dict__.update({'filename':None})or s.set_thumbnail()))(s.__dict__.update({'key':sv.get()})or s.get_filtered_filenames(s.key)))(sv))and None or string_var)(tk.StringVar()),'set_listbox_filenames':lambda s,fn=None:[s.elem_listbox.insert(tk.END, n)for n in s.elem_listbox.delete(0,s.elem_listbox.size()-1)or(fn and fn or s._changer.get_filenames())]+[1]and None,'set_thumbnail':lambda s,fn=None:(not PIL or(lambda thumbnail:((fn and (lambda img:img.thumbnail(s.THUMBNAIL_SIZE,PIL.Image.ANTIALIAS)or thumbnail.paste(img,(int(max((s.THUMBNAIL_SIZE[0]-img.size[0])/2, 0)),int(max((s.THUMBNAIL_SIZE[1]-img.size[1])/2,0)))))(PIL.Image.open(s._changer.get_abspath(fn))))and None)or s.__dict__.update({'thumbnail':PIL.ImageTk.PhotoImage(thumbnail)})or s.elem_thumbnail.configure(image=s.thumbnail))(PIL.Image.new('RGBA', s.THUMBNAIL_SIZE, (0, 0, 0, 0)))or True)and None,'get_filtered_filenames':lambda s,kw:[x for x in s._changer.get_filenames() if x.find(kw) == 0]}))or Gui(tk.Tk(), WallpaperChanger()).mainloop()
It works!!!!
it's end!
thank you for reading!!