Namespaces are one honking great idea
Steven D'Aprano
steve at pearwood.info
Fri Jul 1 13:46:40 EDT 2016
On Sat, 2 Jul 2016 12:49 am, BartC wrote:
> On 01/07/2016 15:13, Steven D'Aprano wrote:
>
>> Sometimes we have a group of related functions and variables that belong
>> together, but are not sufficiently unrelated to the rest of the module
>> that we want to split them out into another file.
>
>> Here's a proof of concept. I use a class with a custom metaclass like
>> this:
>>
>>
>> # Python 3 version
>> class ExampleNS(metaclass=Namespace):
>> x = 1
>> y = []
>>
>> def spam(n):
>> return 'spam'*n
>
>> py> Example.spam(5)
>> 'spamspamspamspamspam'
>
>
> Why not just extend the capabilities of a class?
The usual ways to change the behaviour of classes from Python code is via
decorator, which lets you modify the class after it is created, a
metaclass, which lets you modify it before it is created, or by using
descriptors to customize attribute access.
I'm using a metaclass. When you write:
class K: ...
that is syntactic sugar for calling the default metaclass (`type`) with some
arguments, and `type` then returns the new class K. But if you use a
metaclass (usually, but not necessarily a subclass of `type`) you can
customize the creation of the new class, or even return a completely
different object altogether. That's what I'm doing.
Why am I returning a module instead of a class? Because (1) conceptually a
namespace (in the C++ sense) is like a module; (2) classes have a whole lot
of expectations that aren't relevant to namespaces (like inheritance,
instantiation, "is-a", etc); and (3) it's easy to use a module, which
already provides most of the behaviour I want.
> I actually thought this
> would work until I tried it and it didn't:
>
> class C():
> def fn():
> print ("Hi!")
>
> C.fn()
That actually will work in Python 3. (I had forgotten that.) In Python 2,
you have to inherit C from object, AND decorate fn with staticmethod:
class C(object):
@staticmethod
def fn():
print ("Hi!")
But for my use, that's not enough. I want this to work:
class Foo:
def f():
return g().upper()
def g():
return "hi!"
That is, Foo should behave as if it were a module imported from a file,
except without actually being imported from a file.
--
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