One cannot introduce a new keyword without changing the language
The parser is the tool/program that reads through the code, and decides what makes sense and what doesn't.
Although it's a rather coarse definition, the consequence is that the language is defined by its parser.
The parser relies on the language's (formal) grammar, specified in the ast
module documentation.
While defining a mere function only introduces a new feature without modifying the language, adding a keyword is tantamount to introducing a new syntax, which in turn changes the language's grammar.
Therefore, adding a new keyword, in the sense of adding a new syntax to a language, cannot be made without changing the grammar's language, which requires editing the compilation and execution chain.
However...
There might be some smart ways to introduce a new feature, that looks like a new syntax but in fact only uses the existing syntax.
For instance, the goto module relies on a not-so-well-known property of the language, that the spaces around a dot in a qualified identifier are ignored.
You can try this by yourself:
>>> l = [1, 2, 3]
>>> l .append(4)
>>> l
[1, 2, 3, 4]
>>> l. append(5)
>>> l
[1, 2, 3, 4, 5]
This allows using the following, that looks like a new syntax, but really is not:
label .myLabel
goto .myLabel
Now, the goto
module uses the way the interpreter internally works to perform break from one goto
to a given label
...
But that's another problem.
I'd like to add that Python is quite an open-minded language.
It provides a nice amount of seldom used operators, for instance, @
.
This operator, introduced from Python 3.5, was primarily meant for matrix multiplication, and falls back to a call to __matmul__
.
I have to say, I've never seen it in code.
So, why not use it for your purpose?
Let's do it step-by-step.
I propose to define a r
class, that will behave as a regex.
import re
class r:
def __init__(self, pattern):
self.regex = re.compile(pattern)
Now, I want to be able to use the @
operator with this class, together with a string, with the semantic of a match
between the string and the pattern.
I'll define the __matmul__
method, just as follows:
class r:
def __matmul__(self, string):
return bool(self.regex.match(string))
Now, I can do the following:
>>> r("hello") @ "hello"
True
>>> r("hello"] @ "world"
False
Pretty nice, but not that yet.
I'll define the __rmatmul__
method as well, so it merely falls back to a call to __matmul__
.
In the end, the r
class looks like this:
class r:
def __init__(self, pattern):
self.regex = re.compile(pattern)
def __matmul__(self, string):
return bool(self.regex.match(string))
def __rmatmul__(self, string):
return self @ string
Now, the reverse operation works as well:
>>> "hello" @ r("hello")
True
>>> "123456" @ r("\d+")
True
>>> "abc def" @ r("\S+$")
False
This is very near from what you were attempting, except, I didn't have to introduce a new keyword!
Of course, now the r
identifier must be protected, just like str
or list
...