2

So, after a brief discussion on #python about why not to use locals, I was pondering about what would be a better way without the repetitive nature (i.e. not DRY) of dict(foo=foo,bar=bar) (or the same using the literal syntax ({})).

Ideally, a PEP could be submitted (or one already exists) that mirrors this ecmascript harmony proposal. (I want to promote emphasis on the DRY aspect that it conveys).

So, do you have any solutions? Should I submit a PEP?

4

3 に答える 3

0

My currently proposed solution to this is the following pattern. Please tell me if this is just as bad of a practice as using locals().

class _Context:
    foo = 'bar'
render(request, 'example.html', vars(_Context))

One caveat is that this might be a little iffy with python3 because it will use new-style classes with an immutable dictproxy, and I'd need to see how it would interact with the given templating library. Works fine with a simple '{foo}'.format(**_Context.__dict__).

It is a definite improvement over locals(), since it's fairly explicit, and it doesn't leak other parts of the local scope. However, it does leak '__module__' and '__doc__' with old style classes and a bunch of other stuff with new-style classes.

于 2013-02-21T23:17:04.460 に答える
0

Here's my solution. There might be better ways to structure this, but it works!

Setup (Python 2 and 3):

class ContextDictBase(type):
    @staticmethod
    def __newnew(cls, name, bases, attrs):
        attrs.pop('__module__', None)
        return attrs
    def __new__(cls, name, bases, attrs):
        ContextDictBase.__new__ = staticmethod(ContextDictBase.__newnew)
        return super(ContextDictBase, cls).__new__(cls, name, bases, attrs)

Python 2:

class ContextDict(object):
    __metaclass__ = ContextDictBase

Python 3:

class ContextDict(object, metaclass=ContextDictBase):
    pass

And then to use it:

class context(ContextDict):
    a = 1
    b = 2

>>> context
{'a': 1, 'b': 2}
于 2013-02-22T18:53:34.573 に答える
0

And a variation on the metaclass/attrs solution:

def make_dict(name, bases, attrs):
    attrs.pop('__module__')
    attrs.pop('__metaclass__', None)  # not needed in python3
    return attrs

Python 2:

class Context:
    __metaclass__ = make_dict

Python 3:

class Context(metaclass=make_dict):
    a = 1
    b = 2

Really, this question has just turned into my sandbox for playing with metaclasses

于 2013-03-28T17:58:03.610 に答える