Namespaces are one honking great idea
Steven D'Aprano
steve at pearwood.info
Sat Jul 2 23:44:46 EDT 2016
On Sun, 3 Jul 2016 01:34 am, Kevin Conway wrote:
> staticmethod isn't technically required to use a method through the class
> (or subclasses), it simply provides the appropriate magic to allow it to
> be called through instances.
>
> For example, the following code covers all described use cases of the
> proposed namespace.
It really doesn't. Here's your class:
> Methods are invoked without creating instances and
> state is managed on the class object directly.
>
> class CustomNs:
>
> stateful_data = 1
>
> @staticmethod
> def echo(text):
> print(text)
>
> @classmethod
> def mutate(cls):
> cls.stateful_data += 1
> print(cls.stateful_data)
The class scope is not "first class" (pun intended), as you cannot refer to
class-level variables without prefixing them with the class, even from
within the class.
Although the class *may* be used without instantiating, this violates the
user's expectations and may be confusing.
I acknowledge that my own namespace has a similar problem, as it uses the
class keyword, but the use of an explicit Namespace decorator or metaclass
gives a hint that something is different. And if you try calling the
Namespace, as if to instantiate it, you get a TypeError.
[...]
> For the proponents of namespace, what is deficient in the above example
> that necessitates a language change?
It's not a language change. Although I'd like a new keyword, to avoid
the "but it looks like a class" problem, its not necessary.
Try getting this behaviour from within a class:
class Food(metaclass=Namespace):
# (1) no special decorators required
def spam(n):
return ' '.join(['spam']*n)
# (2) can call functions from inside the namespace
breakfast = spam(5)
# (3) no "cls" or "self" argument
def lunch():
# (4) can access variables using their undotted name
return breakfast + ' and eggs'
def supper():
# (5) likewise functions (a special case of #4)
return lunch() + ' and a fried slice of spam'
def mutate(n):
# global inside the namespace refers to the namespace,
# not the surrounding module
global breakfast
breakfast = spam(5)
Everything written inside the namespace object could have started as top
level module code. I select the code, hit my editor's "Indent" command, and
insert a single line at the top to turn it into a namespace.
If I decide to move the code into a separate file, I just copy the block,
excluding the "class ... metaclass" header line, past into a new file,
select all, and Dedent. Done.
Can you do all of that with an ordinary class?
--
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.
More information about the Python-list
mailing list