Really, the only germane property that the rationals/irrationals have, in the construction of Thomae's functions, is that the rationals are countable and the two sets are complementary. You can generalise the construction like so:
- Let $(x_n)$ be an injective sequence in $\Bbb{R}$.
- Let $(y_n)$ be any sequence in $\Bbb{R}$ such that $y_n \neq 0$ for all $n$, and $y_n \to 0$.
- Define
$$f(x) = \begin{cases}y_n & \text{if there exists } n \in \Bbb{N} \text{ such that } x = x_n \\
0 & \text{otherwise.}\end{cases}$$
Thomae's function can be recovered by taking $(x_n)$ to be the sequence
$$0, 1, \color{blue}{\frac{1}{2}}, \color{green}{\frac{1}{3}}, \color{green}{\frac{2}{3}}, \color{red}{\frac{1}{4}}, \color{red}{\frac{3}{4}}, \color{purple}{\frac{1}{5}}, \color{purple}{\frac{2}{5}}, \color{purple}{\frac{3}{5}}, \color{purple}{\frac{4}{5}}, \color{orange}{\frac{1}{6}}, \color{orange}{\frac{5}{6}}, \ldots$$
i.e. all rational numbers in $[0, 1]$ ordered lexicographically, first by the denominator of their lowest form, then by the numerator of their lowest form. Match it to a sequence $(y_n)$,
$$0, 1, \color{blue}{\frac{1}{2}}, \color{green}{\frac{1}{3}}, \color{green}{\frac{1}{3}}, \color{red}{\frac{1}{4}}, \color{red}{\frac{1}{4}}, \color{purple}{\frac{1}{5}}, \color{purple}{\frac{1}{5}}, \color{purple}{\frac{1}{5}}, \color{purple}{\frac{1}{5}}, \color{orange}{\frac{1}{6}}, \color{orange}{\frac{1}{6}}, \ldots$$
and you get Thomae's function. It's not too difficult to see that $y_n \to 0$; note that only finitely many terms will be larger than any given $\frac{1}{m}$ where $m \in \Bbb{N}$.
The generalised Thomae's function $f$ will be continuous at every point except at the $(x_n)$ points.
At each point $x_m$, any $\delta$-neighbourhood is an uncountable set, meaning a sequence like $(x_n)$ cannot cover the whole neighbourhood. Thus, in any $\delta$-neighbourhood, we will find values of $x$ such that $x \neq x_n$ for all $n$, and so $f(x) = 0$.
If we had continuity at $x_m$, then there would have to exist a $\delta > 0$, corresponding to $\varepsilon = |y_n| > 0$, i.e. such that
$$|x - x_m| < \delta \implies |f(x) - f(x_m)| < \varepsilon \implies |f(x) - y_n| < |y_n|.$$
But, if we let $x$ be an element of the $\delta$-neighbourhood around $x_m$ that doesn't belong to the sequence $(x_n)$, then $f(x) = 0$, so
$$|x - x_m| < \delta \implies |0 - y_n| < |y_n|,$$
a contradiction. Thus, $f$ is discontinuous at all points in the sequence $(x_n)$.
On the other hand, pick a point $x_0$ not in the sequence $(x_n)$ and $\varepsilon > 0$. Since $y_n \to 0$, there exists an $N \in \Bbb{N}$ such that
$$n \ge N \implies |y_n| < \varepsilon.$$
Consider the set of "bad" points $\{x_1, \ldots, x_{N - 1}\}$. This set contains all points $x$ where $|f(x)| \ge \varepsilon$, and it's finite! Take $\delta$ to be the smallest distance from $x_0$ to any of the $N - 1$ points above, and then
$$|x - x_0| < \delta \implies x \notin \{x_1, \ldots, x_{N - 1}\} \implies |f(x) - f(x_0)| = |f(x)| < |y_n| < \varepsilon,$$
proving continuity at $x_0$.