practices - python private variables




Can Python3 class instances be forced to be global objects at initialisation? (2)

Even though global Python objects tend to be bad, I more or less forced to use them with module curses. I currently have this:

class Window:
    def __init__(self, title, h, w, y, x):
        self.window = curses.newwin(h, w, y, x)
        self.window.box()
        self.window.hline(2, 1, curses.ACS_HLINE, w-2)
        self.window.addstr(1, 2, title)
        self.window.refresh()

global top_win
top_win = Window('Top window', 6, 32, 3, 6)

I am wondering whether it would be possible to get rid of the global line by adding something to the class definition or initialisation?

class Window:
    def __init__(self, title, h, w, y, x):
        # Some global self magic
        self.window = curses.newwin(h, w, y, x)
        self.window.box()
        self.window.hline(2, 1, curses.ACS_HLINE, w-2)
        self.window.addstr(1, 2, title)
        self.window.refresh()

top_win = Window('Top window', 6, 32, 3, 6)

Global class pattern

Despite the reflexive downvotes whenever the word global is seen, I resolved my issue anyhow by applying the equally controversial global class pattern.

class win:
    pass

class Window:
    def __init__(self, title, h, w, y, x):
        self.window = curses.newwin(h, w, y, x)
        self.window.box()
        self.window.hline(2, 1, curses.ACS_HLINE, w-2)
        self.window.addstr(1, 2, title)
        self.window.refresh()

win.top = Window('Top window', 6, 32, 3, 6)

This results in win.top being accessible anywhere in my Python script, just like any global variable would have been, but then nice and neat in a more controlled manner.

This is quite handy for defining new curses windows inside the main() routine which is typically wrapped inside a curses.wrapper(main). Follow this link for a full blown Python3 curses example.


How to extend the curses window class in Python3?

So I went for encapsulation rather than inheritance, which is like writing one's own API. I also applied the global class pattern, which is discussed in a separate SE question.

#!/usr/bin/python3

import curses

class win:
    pass

class Window:

    def __init__(self, title, h, w, y, x):
        self.window = curses.newwin(h, w, y, x)
        self.window.box()
        self.window.hline(2, 1, curses.ACS_HLINE, w-2)
        self.window.addstr(1, 2, title)
        self.window.refresh()

    def clear(self):
        for y in range(3, self.window.getmaxyx()[0]-1):
            self.window.move(y,2)
            self.window.clrtoeol()
        self.window.box()

    def addstr(self, y, x, string, attr=0):
        self.window.addstr(y, x, string, attr)

    def refresh(self):
        self.window.refresh()

def main(screen):
    win.top = Window('Top window', 6, 32, 3, 6)
    win.top.addstr(3, 2, 'Test string added.')
    win.top.refresh()
    ch = win.top.getch()

# MAIN
curses.wrapper(main)