Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #110899 > unrolled thread

Namespaces are one honking great idea

Started bySteven D'Aprano <steve@pearwood.info>
First post2016-07-02 00:13 +1000
Last post2016-07-09 07:05 -0700
Articles 16 on this page of 36 — 12 participants

Back to article view | Back to comp.lang.python


Contents

  Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-02 00:13 +1000
    Re: Namespaces are one honking great idea Random832 <random832@fastmail.com> - 2016-07-01 10:40 -0400
    Re: Namespaces are one honking great idea BartC <bc@freeuk.com> - 2016-07-01 15:49 +0100
      Re: Namespaces are one honking great idea Chris Angelico <rosuav@gmail.com> - 2016-07-02 03:13 +1000
      Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-02 03:46 +1000
      Re: Namespaces are one honking great idea Rustom Mody <rustompmody@gmail.com> - 2016-07-01 19:26 -0700
    Re: Namespaces are one honking great idea Ethan Furman <ethan@stoneleaf.us> - 2016-07-01 09:00 -0700
      Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-02 03:10 +1000
        Re: Namespaces are one honking great idea Ethan Furman <ethan@stoneleaf.us> - 2016-07-01 12:29 -0700
          Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-02 11:07 +1000
            Re: Namespaces are one honking great idea Kevin Conway <kevinjacobconway@gmail.com> - 2016-07-02 01:50 +0000
              Re: Namespaces are one honking great idea Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-07-01 19:55 -0700
              Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-03 13:22 +1000
            Re: Namespaces are one honking great idea Random832 <random832@fastmail.com> - 2016-07-02 00:59 -0400
            Re: Namespaces are one honking great idea Kevin Conway <kevinjacobconway@gmail.com> - 2016-07-02 15:34 +0000
              Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-03 13:44 +1000
                Re: Namespaces are one honking great idea Ethan Furman <ethan@stoneleaf.us> - 2016-07-02 22:14 -0700
                Re: Namespaces are one honking great idea Kevin Conway <kevinjacobconway@gmail.com> - 2016-07-03 22:02 +0000
                  Re: Namespaces are one honking great idea Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-07-03 16:21 -0700
                    Re: Namespaces are one honking great idea BartC <bc@freeuk.com> - 2016-07-04 01:19 +0100
                Re: Namespaces are one honking great idea Ethan Furman <ethan@stoneleaf.us> - 2016-07-03 21:01 -0700
            Re: Namespaces are one honking great idea Ethan Furman <ethan@stoneleaf.us> - 2016-07-02 16:28 -0700
    Re: Namespaces are one honking great idea Chris Angelico <rosuav@gmail.com> - 2016-07-04 21:37 +1000
      Re: Namespaces are one honking great idea Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-07-04 15:09 -0700
        Re: Namespaces are one honking great idea Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-07-04 15:11 -0700
    Re: Namespaces are one honking great idea jmp <jeanmichel@sequans.com> - 2016-07-04 17:58 +0200
    Re: Namespaces are one honking great idea Chris Angelico <rosuav@gmail.com> - 2016-07-05 12:58 +1000
      Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-05 13:35 +1000
        Re: Namespaces are one honking great idea Chris Angelico <rosuav@gmail.com> - 2016-07-05 13:47 +1000
          Re: Namespaces are one honking great idea Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-07-05 16:09 +1000
            A nestedmodule decorator (Re: Namespaces are one honking great idea) Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-07-05 21:10 +1200
              Improved nestedmodule decorator implementation Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-07-05 21:31 +1200
                Re: Improved nestedmodule decorator implementation Steven D'Aprano <steve@pearwood.info> - 2016-07-05 20:54 +1000
    Re: Namespaces are one honking great idea Steven D'Aprano <steve@pearwood.info> - 2016-07-05 12:34 +1000
    Re: Namespaces are one honking great idea jmp <jeanmichel@sequans.com> - 2016-07-04 13:23 +0200
    Re: Namespaces are one honking great idea carlosjosepita@gmail.com - 2016-07-09 07:05 -0700

Page 2 of 2 — ← Prev page 1 [2]


#111058

FromEthan Furman <ethan@stoneleaf.us>
Date2016-07-03 21:01 -0700
Message-ID<mailman.57.1467605360.2295.python-list@python.org>
In reply to#110971
On 07/03/2016 03:02 PM, Kevin Conway wrote:
 >At some point earlier Ethan Furman declared:

>> It's not a language change.
>
> Perhaps. My argument is that anything that introduces a new class-like
> construct and set of lexical scoping rules is a language change. For
> example, if this change went into 2.7.13 would Jython suddenly be broken
> because it hasn't implemented the new scoping rules?

It's not a language change*.  There is nothing for Jython, IronPython, 
Brython, etc., to implement.  No scoping rule changes, nothing.  The 
magic in Steven's name space is implemented by the metaclass by 
(presumably) rebuilding all the functions -- and that is how he manages 
the effective scoping rules.

--
~Ethan~


*Okay, it is not a language change the same way the addition of Enum was 
not a language change.  On the other hand, asyncio did have some 
language changes (await, async, etc.).

[toc] | [prev] | [next] | [standalone]


#110966

FromEthan Furman <ethan@stoneleaf.us>
Date2016-07-02 16:28 -0700
Message-ID<mailman.31.1467502094.2295.python-list@python.org>
In reply to#110924
On 07/02/2016 08:34 AM, Kevin Conway wrote:

> For the proponents of namespace, what is deficient in the above example
> that necessitates a language change?

Adding a new widget is not changing the language.

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#111043

FromChris Angelico <rosuav@gmail.com>
Date2016-07-04 21:37 +1000
Message-ID<mailman.67.1467632250.2295.python-list@python.org>
In reply to#110899
On Mon, Jul 4, 2016 at 9:23 PM, jmp <jeanmichel@sequans.com> wrote:
> On 07/01/2016 04:13 PM, Steven D'Aprano wrote:
>>
>> But classes are not like the others: they must be instantiated before they
>> can be used, and they are more than just a mere namespace grouping related
>> entities. Classes support inheritance. Classes should be used for "is-a"
>> relationships, not "has-a" relationships. Although classes (and instances)
>> are namespaces, they provide fundamentally different kind of behaviour
>> than
>> modules and packages.
>
>
> A namespace would not hurt but I really don't get why you don't consider
> classes a valid and rather helpful namespace.
>
> 1/ classes do not have to be instantiated.
> 2/ the fact that classes are more than a namespace is not an argument.
> Almost any object in python is able to do more than what you are actually
> using.
> 3/ Classes are used as much as 'is-a' than 'has-a', class instances *have* a
> state usually described by attributes
> 4/ "Although classes (and instances) are namespaces, ". You seem to
> contradict yourself. It was probably a rhetorical construct but it's rather
> confusing.

Functions within the namespace can't call other functions within the
same namespace using unqualified names. This was a stated requirement.

ChrisA

[toc] | [prev] | [next] | [standalone]


#111050

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-07-04 15:09 -0700
Message-ID<d06cc82d-c035-4a41-99ab-cb3e043f9e93@googlegroups.com>
In reply to#111043
On Monday, July 4, 2016 at 11:37:44 PM UTC+12, Chris Angelico wrote:

> Functions within the namespace can't call other functions within the
> same namespace using unqualified names. This was a stated requirement.

Doesn’t my @namespace decorator provide that?

[toc] | [prev] | [next] | [standalone]


#111052

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-07-04 15:11 -0700
Message-ID<17c5d75a-f01d-467f-95f8-1e7228403722@googlegroups.com>
In reply to#111050
On Tuesday, July 5, 2016 at 10:10:04 AM UTC+12, I wrote:
>
> On Monday, July 4, 2016 at 11:37:44 PM UTC+12, Chris Angelico wrote:
> 
> > Functions within the namespace can't call other functions within the
> > same namespace using unqualified names. This was a stated requirement.
> 
> Doesn’t my @namespace decorator provide that?

No it doesn’t.

[toc] | [prev] | [next] | [standalone]


#111072

Fromjmp <jeanmichel@sequans.com>
Date2016-07-04 17:58 +0200
Message-ID<mailman.71.1467647921.2295.python-list@python.org>
In reply to#110899
On 07/04/2016 01:37 PM, Chris Angelico wrote:
> On Mon, Jul 4, 2016 at 9:23 PM, jmp <jeanmichel@sequans.com> wrote:
>> On 07/01/2016 04:13 PM, Steven D'Aprano wrote:
>>>
>>> But classes are not like the others: they must be instantiated before they
>>> can be used, and they are more than just a mere namespace grouping related
>>> entities. Classes support inheritance. Classes should be used for "is-a"
>>> relationships, not "has-a" relationships. Although classes (and instances)
>>> are namespaces, they provide fundamentally different kind of behaviour
>>> than
>>> modules and packages.
>>
>>
>> A namespace would not hurt but I really don't get why you don't consider
>> classes a valid and rather helpful namespace.
>>
>> 1/ classes do not have to be instantiated.
>> 2/ the fact that classes are more than a namespace is not an argument.
>> Almost any object in python is able to do more than what you are actually
>> using.
>> 3/ Classes are used as much as 'is-a' than 'has-a', class instances *have* a
>> state usually described by attributes
>> 4/ "Although classes (and instances) are namespaces, ". You seem to
>> contradict yourself. It was probably a rhetorical construct but it's rather
>> confusing.
>
> Functions within the namespace can't call other functions within the
> same namespace using unqualified names. This was a stated requirement.
>
> ChrisA
>

Ho, I missed that one.

But if it's the only missing requirement, wouldn't be like stating that 
python instances are not instances because methods cannot call other 
methods without "self."ed qualified name ? We like explicit qualified 
stuff in python right ? ("explicit is better than implicit")

jm


[toc] | [prev] | [next] | [standalone]


#111074

FromChris Angelico <rosuav@gmail.com>
Date2016-07-05 12:58 +1000
Message-ID<mailman.81.1467687507.2295.python-list@python.org>
In reply to#110899
On Tue, Jul 5, 2016 at 12:34 PM, Steven D'Aprano <steve@pearwood.info> wrote:
> *** IF *** you are willing to push the code out into its own separate .py
> file, you can use a module and write your code in a more natural form:
>
>
> # module example.py
> var = 999
>
> def spam(arg):
>     return eggs(arg) + var
>
> def eggs(arg):
>     return arg*2
>
>
> What I'm calling a "namespace" is just a module object that lives inside
> another module, without requiring a separate .py file. It only uses
> the "class" statement for pragmatic reasons: there's no other statement
> available that will do the job.

If you push your code into a separate .py file, you can reference the
original module by importing it. Is that also the normal way to use
"outer" functions etc from inside a namespace?

# demo.py
pi = 3.14
def stupidfib(x):
    if x < 2: return x
    return stupidfib(x-1) + stupidfib(x-2)


Namespace asdf: # (or class, however it's done)
    def foo(x):
        return stupidfib(x * pi) / pi

How should foo reference those "even more global" names? "from .
import pi, stupidfib" would work if you converted the module into a
package ("mv demo.py demo/__init__.py"), and "from demo import pi,
stupidfib" would work if you converted the namespace into a peer
module. Either could make sense.

ChrisA

[toc] | [prev] | [next] | [standalone]


#111091

FromSteven D'Aprano <steve@pearwood.info>
Date2016-07-05 13:35 +1000
Message-ID<577b2af3$0$1611$c3e8da3$5496439d@news.astraweb.com>
In reply to#111074
On Tue, 5 Jul 2016 12:58 pm, Chris Angelico wrote:

> On Tue, Jul 5, 2016 at 12:34 PM, Steven D'Aprano <steve@pearwood.info>
> wrote:
>> *** IF *** you are willing to push the code out into its own separate .py
>> file, you can use a module and write your code in a more natural form:
>>
>>
>> # module example.py
>> var = 999
>>
>> def spam(arg):
>>     return eggs(arg) + var
>>
>> def eggs(arg):
>>     return arg*2
>>
>>
>> What I'm calling a "namespace" is just a module object that lives inside
>> another module, without requiring a separate .py file. It only uses
>> the "class" statement for pragmatic reasons: there's no other statement
>> available that will do the job.
> 
> If you push your code into a separate .py file, you can reference the
> original module by importing it. Is that also the normal way to use
> "outer" functions etc from inside a namespace?

Good question! 

With the current implementation, importing should work, but it's not
necessary. The surrounding module (the real .py module) is inserted into
the name resolution path of functions:

py> x = 999
py> @namespace.Namespace
... class Test:
...     def test():
...             print(x)
...
py> Test.test()
999


Of course, the module-global x will be shadowed by any x in the Test
namespace (which is the intent), and you cannot assign to them (also a
feature). A bare `x = 1` inside the function will make x a local, unless
you declare it global first, in which case it should assign to the Test
namespace scope instead.




-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

[toc] | [prev] | [next] | [standalone]


#111094

FromChris Angelico <rosuav@gmail.com>
Date2016-07-05 13:47 +1000
Message-ID<mailman.82.1467690470.2295.python-list@python.org>
In reply to#111091
On Tue, Jul 5, 2016 at 1:35 PM, Steven D'Aprano <steve@pearwood.info> wrote:
>> If you push your code into a separate .py file, you can reference the
>> original module by importing it. Is that also the normal way to use
>> "outer" functions etc from inside a namespace?
>
> Good question!
>
> With the current implementation, importing should work, but it's not
> necessary. The surrounding module (the real .py module) is inserted into
> the name resolution path of functions:
>
> py> x = 999
> py> @namespace.Namespace
> ... class Test:
> ...     def test():
> ...             print(x)
> ...
> py> Test.test()
> 999

Ah, fascinating. This does break the "just unindent and move to a new
file if you want to break it out" equivalency, but it does make sense
- it's a *nested* namespace, which modules (even in a package) are
not. So you have the outer namespace acting pretty much the way
builtins do. (Do nested namespaces work?)

ChrisA

[toc] | [prev] | [next] | [standalone]


#111103

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2016-07-05 16:09 +1000
Message-ID<577b4f06$0$2752$c3e8da3$76491128@news.astraweb.com>
In reply to#111094
On Tuesday 05 July 2016 13:47, Chris Angelico wrote:

> On Tue, Jul 5, 2016 at 1:35 PM, Steven D'Aprano <steve@pearwood.info> wrote:
>>> If you push your code into a separate .py file, you can reference the
>>> original module by importing it. Is that also the normal way to use
>>> "outer" functions etc from inside a namespace?
>>
>> Good question!
>>
>> With the current implementation, importing should work, but it's not
>> necessary. The surrounding module (the real .py module) is inserted into
>> the name resolution path of functions:
>>
>> py> x = 999
>> py> @namespace.Namespace
>> ... class Test:
>> ...     def test():
>> ...             print(x)
>> ...
>> py> Test.test()
>> 999
> 
> Ah, fascinating. This does break the "just unindent and move to a new
> file if you want to break it out" equivalency, but it does make sense
> - it's a *nested* namespace, which modules (even in a package) are
> not. So you have the outer namespace acting pretty much the way
> builtins do. (Do nested namespaces work?)

I haven't got that far, but I expect that nested namespaces will be nested in 
name only, like nested functions in Python 1.5.

There's only so far I can go without support from the compiler. If you nest a 
class inside another class, the inner class doesn't see variables in the outer 
class even during construction. So I'm pretty sure my namespace metaclass will 
inherit the same limitation.



-- 
Steve

[toc] | [prev] | [next] | [standalone]


#111113 — A nestedmodule decorator (Re: Namespaces are one honking great idea)

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2016-07-05 21:10 +1200
SubjectA nestedmodule decorator (Re: Namespaces are one honking great idea)
Message-ID<du1brpFe32qU1@mid.individual.net>
In reply to#111103
Steven D'Aprano wrote:
> There's only so far I can go without support from the compiler.

It turns out one can go surprisingly far. Here's something I
cooked up that seems to meet almost all the requirements.
The only shortcoming I can think of is that a nestedmodule
inside another nestedmodule won't be able to see the names
in the outer nestedmodule directly (much like nested classes).

% python3 test_nestedmodule.py
0.7071067811865475

#------------------------------------------
#
#   test_nestedmodule.py
#
#------------------------------------------

from math import pi, sin
from nestedmodule import nestedmodule

def f(x):
     return x**2

@nestedmodule
def test():

     def g(x):
         return f(x) * pi

     def h(x):
         return sin(g(x))

y = test.h(0.5)
print(y)

#------------------------------------------
#
#   nestedmodule.py
#
#------------------------------------------

from types import CodeType, ModuleType

def hack_code(f):
     """Hack 'return locals()' onto the end of the bytecode of f."""
     code1 = f.__code__
     bytes1 = code1.co_code
     names1 = code1.co_names
     n = len(names1)
     names2 = names1 + ('locals',)
     bytes2 = bytes1[:-4] + bytes([116, n, 0, 131, 0, 0, 83])
     code2 = CodeType(code1.co_argcount, code1.co_kwonlyargcount, code1.co_nlocals,
         code1.co_stacksize, code1.co_flags, bytes2, code1.co_consts, names2,
         code1.co_varnames, code1.co_filename, code1.co_name, code1.co_firstlineno,
         code1.co_lnotab, code1.co_freevars, code1.co_cellvars)
     return code2

def nestedmodule(f):
     c = hack_code(f)
     l = eval(c, f.__globals__)
     m = ModuleType(f.__name__)
     m.__dict__.update(l)
     return m

[toc] | [prev] | [next] | [standalone]


#111117 — Improved nestedmodule decorator implementation

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2016-07-05 21:31 +1200
SubjectImproved nestedmodule decorator implementation
Message-ID<du1d4aFebp4U1@mid.individual.net>
In reply to#111113
I wrote:
> The only shortcoming I can think of is that a nestedmodule
> inside another nestedmodule won't be able to see the names
> in the outer nestedmodule

Actually, that's not correct -- the version I posted before
actually crashes if you try to refer to a name in an outer
nestedmodule from an inner nestedmodule.

Here's an improved version that fully supports nesting to
any depth.

% python3 test_nested_nested.py
foo
blarg

#------------------------------------------
#
#   test_nested_nested.py
#
#------------------------------------------

from nestedmodule import nestedmodule

@nestedmodule
def m1():

     def foo():
         print("foo")

     @nestedmodule
     def m2():

         def blarg():
             foo()
             print("blarg")

m1.m2.blarg()

#------------------------------------------
#
#   nestedmodule.py
#
#------------------------------------------

from types import CodeType, FunctionType, ModuleType
from dis import dis

def hack_code(f):
     """Hack 'return locals()' onto the end of the bytecode of f."""
     code1 = f.__code__
     bytes1 = code1.co_code
     names1 = code1.co_names
     n = len(names1)
     names2 = names1 + ('locals',)
     bytes2 = bytes1[:-4] + bytes([116, n, 0, 131, 0, 0, 83])
     code2 = CodeType(code1.co_argcount, code1.co_kwonlyargcount, code1.co_nlocals,
         code1.co_stacksize, code1.co_flags, bytes2, code1.co_consts, names2,
         code1.co_varnames, code1.co_filename, code1.co_name, code1.co_firstlineno,
         code1.co_lnotab, code1.co_freevars, code1.co_cellvars)
     f2 = FunctionType(code2, f.__globals__, f.__name__, f.__kwdefaults__, 
f.__closure__)
     return f2

def nestedmodule(f):
     f2 = hack_code(f)
     l = f2()
     m = ModuleType(f.__name__)
     m.__dict__.update(l)
     return m

[toc] | [prev] | [next] | [standalone]


#111121 — Re: Improved nestedmodule decorator implementation

FromSteven D'Aprano <steve@pearwood.info>
Date2016-07-05 20:54 +1000
SubjectRe: Improved nestedmodule decorator implementation
Message-ID<577b91ca$0$1620$c3e8da3$5496439d@news.astraweb.com>
In reply to#111117
On Tue, 5 Jul 2016 07:31 pm, Gregory Ewing wrote:

> I wrote:
>> The only shortcoming I can think of is that a nestedmodule
>> inside another nestedmodule won't be able to see the names
>> in the outer nestedmodule
> 
> Actually, that's not correct -- the version I posted before
> actually crashes if you try to refer to a name in an outer
> nestedmodule from an inner nestedmodule.
> 
> Here's an improved version that fully supports nesting to
> any depth.

That's impressive. And scary. And I fear not portable, since it uses
byte-code hacking.

But still nicely done.




-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

[toc] | [prev] | [next] | [standalone]


#111086

FromSteven D'Aprano <steve@pearwood.info>
Date2016-07-05 12:34 +1000
Message-ID<577b1cc6$0$1584$c3e8da3$5496439d@news.astraweb.com>
In reply to#110899
On Mon, 4 Jul 2016 09:23 pm, jmp wrote:

> On 07/01/2016 04:13 PM, Steven D'Aprano wrote:
>> But classes are not like the others: they must be instantiated before
>> they can be used, and they are more than just a mere namespace grouping
>> related entities. Classes support inheritance. Classes should be used for
>> "is-a" relationships, not "has-a" relationships. Although classes (and
>> instances) are namespaces, they provide fundamentally different kind of
>> behaviour than modules and packages.
> 
> A namespace would not hurt but I really don't get why you don't consider
> classes a valid and rather helpful namespace.

I never said that.

This is where the term "namespace" can be ambiguous. "Namespace" can refer
to any of:

- an abstract mapping of symbols (names) to values;

- specific kinds of namespaces:

  * the concrete C++/C#/PHP data type called "namespace";
  * Python packages and modules;
  * classes;
  * instances of a class;

- the implementation (the __dict__ attribute of modules, classes);

etc. Now clearly a class is not the same thing as the class __dict__, and a
module is not the same as a class, and neither modules nor classes are the
same as a C++ namespace. Doesn't mean that classes aren't valid namespaces,
just that their semantics, use-cases and behaviour are different to those
of modules.



> 1/ classes do not have to be instantiated.

That's a bit of a sore point to me.

Some years ago I wrote here to ask what name is given to a class that is not
instantiated before being used. Singleton classes get instantiated once,
allowing a single instance. What if you had a class that didn't need
instantiating at all, so that the class itself was *effectively* the
singleton? What should that be called?


Instead of this:

    class SingletonClass:
        ...

    singleton = SingletonClass()
    singleton.method()


what if we had this instead?

    class singleton:
        ...

    singleton.method()


I was roundly told that this was crazy talk, that the whole point of classes
was that they must be instantiated to use them, that code like the second
example would be confusing and very possibly bring about the fall of
Western Civilisation. The idea that this might be a legitimate alternative
to the singleton design pattern was dismissed.

(The Python community is terribly conservative when it comes to code.)

And, in a sense, they were right: there are two common ways to get
singleton-like behaviour in general, and in Python specifically:

- use class that allows only a single instance;

- use a module.

Using the class itself is unusual and surprising (especially to Java
programmers, where classes aren't even first-class values), and more so,
it's *inconvenient*.

To write a class which is used without instantiation, you should raise an
error on instantiation, decorate every method using classmethod or
staticmethod, and have methods have to call each other using the dotted
name:

class Example:
    var = 999

    def __init__(self):
        raise TypeError('do not instantiate this class')

    @classmethod
    def spam(cls, arg):
        return cls.eggs(arg) + cls.var

    @classmethod
    def eggs(cls, arg):
        return arg*2


*** IF *** you are willing to push the code out into its own separate .py
file, you can use a module and write your code in a more natural form:


# module example.py
var = 999

def spam(arg):
    return eggs(arg) + var

def eggs(arg):
    return arg*2


What I'm calling a "namespace" is just a module object that lives inside
another module, without requiring a separate .py file. It only uses
the "class" statement for pragmatic reasons: there's no other statement
available that will do the job.


> 2/ the fact that classes are more than a namespace is not an argument.
> Almost any object in python is able to do more than what you are
> actually using.

There's one aspect of classes that is a deliberate design feature, but goes
against what I'm after: the fact that the class namespace itself is NOT
part of the method name resolution rules (except during class
construction). Try this:

x = 999

class Example:
    x = 1
    print(x)  # called during class construction
    @classmethod
    def test(cls):
        print(x)


Example.test()



This will print 1, then 999. We quite often get people complaining about
this. I'm not one of them. I want classes to keep the current rules. But it
shows that a class is not the right answer for a module-inside-a-module
object.


> 3/ Classes are used as much as 'is-a' than 'has-a', class instances
> *have* a state usually described by attributes

Instances have state, of course, but the relationship I'm talking about is
instance to class.

class Dog:
    ...

lassie = Dog()

Lassie is a dog, not "Lassie has a dog".

Lassie has a tail, not "Lassie is a tail".


That's why we have IS_instance and HAS_attr builtins.

The expectation is that a class represents a model of a physical kind of
thing, whether that's a Dog or a HTTPServer or a float. If you want a
collection of related functions, classes and variables, put them in a
different kind of namespace, namely a module (if using a separate .py file
is okay) or a Namespace.





-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

[toc] | [prev] | [next] | [standalone]


#111088

Fromjmp <jeanmichel@sequans.com>
Date2016-07-04 13:23 +0200
Message-ID<mailman.65.1467631737.2295.python-list@python.org>
In reply to#110899
On 07/01/2016 04:13 PM, Steven D'Aprano wrote:
> But classes are not like the others: they must be instantiated before they
> can be used, and they are more than just a mere namespace grouping related
> entities. Classes support inheritance. Classes should be used for "is-a"
> relationships, not "has-a" relationships. Although classes (and instances)
> are namespaces, they provide fundamentally different kind of behaviour than
> modules and packages.

A namespace would not hurt but I really don't get why you don't consider 
classes a valid and rather helpful namespace.

1/ classes do not have to be instantiated.
2/ the fact that classes are more than a namespace is not an argument. 
Almost any object in python is able to do more than what you are 
actually using.
3/ Classes are used as much as 'is-a' than 'has-a', class instances 
*have* a state usually described by attributes
4/ "Although classes (and instances) are namespaces, ". You seem to 
contradict yourself. It was probably a rhetorical construct but it's 
rather confusing.

jm

[toc] | [prev] | [next] | [standalone]


#111223

Fromcarlosjosepita@gmail.com
Date2016-07-09 07:05 -0700
Message-ID<221b0501-eeb1-4c93-aa83-6c73854299c4@googlegroups.com>
In reply to#110899
Hi all,

although it doesn't fit the bill 100%, I sometimes use this extremely simple function as a decorator:

def new(call):
    return call()


For example:

@new
class MySingleton:
    x = 2
    y = 2
    def sum(self, x, y):
        return x + y


@new
def my_obj():
    x = 2
    y = 2
    def sum(x, y):
        return x + y
    return Bundle(locals())


where Bundle is a simple subclass of dict implementing __xxxattr__ dunder methods.

Cheers
--
Carlos


 

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web