469,275 Members | 1,818 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,275 developers. It's quick & easy.

Metaclasses and class variables

Hi!

I am new to this list, and maybe this is a stupid question, but I
can't seem to find _any_ kind of answer anywhere.

What I want to do is the following:
I want to insert a class variable into a class upon definition and
actually use it during definition.

Manually, that is possible, e.g.:

class A:
classvar = []
classvar.append(1)
classvar.append(2)

I don't want to explicitly set the variable, though. My idea was to
write the following:

class Meta(type):
def __new__(cls, name, bases, d):
d['classvar'] = []
return type.__new__(cls, name, bases, d)

class Test:
__metaclass__ = Meta

classvar.append(1)
classvar.append(2)

However, Python complains that the variable isn't defined; it can be
found in the class dictionary _after_ definition, though, and then it
can also be used. But where's the conceptual difference (to the manual
approach)?

Thanks in advance,
Ole
Aug 4 '05 #1
8 1431
Jan-Ole Esleben wrote:
class Meta(type):
def __new__(cls, name, bases, d):
d['classvar'] = []
return type.__new__(cls, name, bases, d)


The problem is that __new__ is called upon object construction, not
class definition, but you're trying to set the class variables at
definition-time.
Aug 4 '05 #2
I thought __new__ was called upon construction of the _class_ object
that "Meta" is the type of. Then it would be available at the time of
the definition of my class. Or am I mistaken?

Ole

2005/8/4, Christopher Subich <sp****************@block.subich.spam.com>:
Jan-Ole Esleben wrote:
class Meta(type):
def __new__(cls, name, bases, d):
d['classvar'] = []
return type.__new__(cls, name, bases, d)


The problem is that __new__ is called upon object construction, not
class definition, but you're trying to set the class variables at
definition-time.
--
http://mail.python.org/mailman/listinfo/python-list

Aug 4 '05 #3
Jan-Ole Esleben <es*****@gmail.com> writes:
Hi!

I am new to this list, and maybe this is a stupid question, but I
can't seem to find _any_ kind of answer anywhere.

What I want to do is the following:
I want to insert a class variable into a class upon definition and
actually use it during definition.

Manually, that is possible, e.g.:

class A:
classvar = []
classvar.append(1)
classvar.append(2)

I don't want to explicitly set the variable, though. My idea was to
write the following:

class Meta(type):
def __new__(cls, name, bases, d):
d['classvar'] = []
return type.__new__(cls, name, bases, d)

class Test:
__metaclass__ = Meta

classvar.append(1)
classvar.append(2)

However, Python complains that the variable isn't defined; it can be
found in the class dictionary _after_ definition, though, and then it
can also be used. But where's the conceptual difference (to the manual
approach)?


classvar is defined AFTER the class has been created. So, this should
work:

class Test:
__metaclass__ = Meta

Test.classvar.append(1)

Thomas
Aug 4 '05 #4
Christopher Subich wrote:
Jan-Ole Esleben wrote:
class Meta(type):
def __new__(cls, name, bases, d):
d['classvar'] = []
return type.__new__(cls, name, bases, d)

The problem is that __new__ is called upon object construction, not
class definition, but you're trying to set the class variables at
definition-time.


The metaclass __new__() is called on class creation (the class is the object being constructed) but not until after the body of the class definition is executed; the dictionary passed to __new__() contains the methods and class variables defined by the class statement.

See http://www.python.org/2.2/descrintro.html#metaclasses

Kent
Aug 4 '05 #5
Yes, that works, but it is unfortunately not an option (at least not a
good one).

Is there no way to create a class variable that exists during
definition of the class? (I cannot imagine there isn't, since
technically it's possible and manually it can be done...)

Ole

classvar is defined AFTER the class has been created. So, this should
work:

class Test:
__metaclass__ = Meta

Test.classvar.append(1)

Thomas
--
http://mail.python.org/mailman/listinfo/python-list

Aug 4 '05 #6
Jan-Ole Esleben wrote:
Yes, that works, but it is unfortunately not an option (at least not a
good one).

Is there no way to create a class variable that exists during
definition of the class? (I cannot imagine there isn't, since
technically it's possible and manually it can be done...)

Ole

The metaclass hook occurs *after* class definition, anything using a
side-effect of a metaclass hook then, *must* occur after the execution
of the metaclass hook. At the time you want to write classvar.append
the "class" is only a namespace, so, if you really need this feature
you'll need to look elsewhere for at least *part* of the solution.

A global "classvar" that, when appended to, caches values until your
metaclass is called and transfers the cache to the class should *work*,
but egads that's ugly compared to just classvar = [] . I guess what I'd
ask is *why* is avoiding that single line so important. It could be
there's a reasonable answer, but the amount of machinery required to
avoid it is going to be significant.

class meta( type ):
newClassVar = []
def __new__( cls, name, bases, dictionary ):
dictionary[ 'classvar' ] = cls.newClassVar[:]
del cls.newClassVar[:]
return super( meta, cls ).__new__( cls, name, bases, dictionary )
__metaclass__ = meta
classvar = meta.newClassVar

or something along those lines...

Um, ick, but HTH,
Mike

--
________________________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com

Aug 4 '05 #7
Thanks! It's a bit icky, yes, but I've been so wrapped up in
complicated thinking that I didn't see this. It's actually quite an
OK solution (I need it because I have an internal representation for
method interfaces that needs to be saved somewhere without the user
having to worry about it, and without them having to set variables.
Method interfaces are class specific, and the only other thing I could
do would be to have a dictionary of classes somewhere, but as the
class itself uses its interface I can't see any really sensible way to
go about this differently).

Ole
2005/8/4, Mike C. Fletcher <mc******@rogers.com>:
Jan-Ole Esleben wrote:
Yes, that works, but it is unfortunately not an option (at least not a
good one).

Is there no way to create a class variable that exists during
definition of the class? (I cannot imagine there isn't, since
technically it's possible and manually it can be done...)

Ole

The metaclass hook occurs *after* class definition, anything using a
side-effect of a metaclass hook then, *must* occur after the execution
of the metaclass hook. At the time you want to write classvar.append
the "class" is only a namespace, so, if you really need this feature
you'll need to look elsewhere for at least *part* of the solution.

A global "classvar" that, when appended to, caches values until your
metaclass is called and transfers the cache to the class should *work*,
but egads that's ugly compared to just classvar = [] . I guess what I'd
ask is *why* is avoiding that single line so important. It could be
there's a reasonable answer, but the amount of machinery required to
avoid it is going to be significant.

class meta( type ):
newClassVar = []
def __new__( cls, name, bases, dictionary ):
dictionary[ 'classvar' ] = cls.newClassVar[:]
del cls.newClassVar[:]
return super( meta, cls ).__new__( cls, name, bases, dictionary )
__metaclass__ = meta
classvar = meta.newClassVar

or something along those lines...

Um, ick, but HTH,
Mike

--
________________________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com

Aug 4 '05 #8
On Thu, 4 Aug 2005 17:53:28 +0200, Jan-Ole Esleben <es*****@gmail.com> wrote:
Thanks! It's a bit icky, yes, but I've been so wrapped up in
complicated thinking that I didn't see this. It's actually quite an
OK solution (I need it because I have an internal representation for
method interfaces that needs to be saved somewhere without the user
having to worry about it, and without them having to set variables.
Method interfaces are class specific, and the only other thing I could
do would be to have a dictionary of classes somewhere, but as the
class itself uses its interface I can't see any really sensible way to
go about this differently).

Ole
2005/8/4, Mike C. Fletcher <mc******@rogers.com>:
Jan-Ole Esleben wrote:
=20
>Yes, that works, but it is unfortunately not an option (at least not a
>good one).
>
>Is there no way to create a class variable that exists during
>definition of the class? (I cannot imagine there isn't, since
>technically it's possible and manually it can be done...)
>
>Ole
>
>

The metaclass hook occurs *after* class definition, anything using a
side-effect of a metaclass hook then, *must* occur after the execution
of the metaclass hook. At the time you want to write classvar.append
the "class" is only a namespace, so, if you really need this feature
you'll need to look elsewhere for at least *part* of the solution.
=20
A global "classvar" that, when appended to, caches values until your
metaclass is called and transfers the cache to the class should *work*,
but egads that's ugly compared to just classvar =3D [] . I guess what I'=

d
ask is *why* is avoiding that single line so important. It could be
there's a reasonable answer, but the amount of machinery required to
avoid it is going to be significant.
=20
class meta( type ):
newClassVar =3D []
def __new__( cls, name, bases, dictionary ):
dictionary[ 'classvar' ] =3D cls.newClassVar[:]
del cls.newClassVar[:]
return super( meta, cls ).__new__( cls, name, bases, dictionary )
__metaclass__ =3D meta
classvar =3D meta.newClassVar
=20
or something along those lines...
=20
Um, ick, but HTH,
Mike
=20
-- What about using a closure variable instead of the global mentioned above? E.g.,
def cfactory(): ... classvar = []
... class TheClass(object):
... classvar.append(1)
... classvar.append(2)
... TheClass.classvar = classvar
... return TheClass
... tc = cfactory()
tc <class '__main__.TheClass'> tc.classvar [1, 2]

I'm wondering what the real problem is. If you are creating some kind of class
variable that accumulates things related to methods, why can't the metaclass do
the whole job after the methods have all been defined cleanly?

OTOH, if not, have you considered that decorators execute a def-time of the decorated
functions -- which for methods defined in class scope will be during class definition
execution. E.g., you could make classvars accessible through a base class and pump into
via decorators (note that you can decorate with Base.deco or bind it by itself as below)
class Base(object): ... classvar = []
... @classmethod
... def deco(cls, f):
... cls.classvar.append((f.func_name, f.func_code.co_argcount))
... deco = Base.deco
class TheClass(Base): ... @deco
... def foo(): pass
... @Base.deco
... def bar(x, y): print 'two args:', x, y
... TheClass.classvar [('foo', 0), ('bar', 2)]

Incidentally, you can see that deco and classvar belong to the Base class, though
accessible as instance and class attributes
tc = TheClass()
tc.classvar [('foo', 0), ('bar', 2)] TheClass.mro() [<class '__main__.TheClass'>, <class '__main__.Base'>, <type 'object'>] vars(tc) {} vars(TheClass).keys() ['__module__', 'foo', 'bar', '__doc__'] vars(Base).keys()

['__module__', 'deco', 'classvar', '__dict__', '__weakref__', '__doc__']

HTH. Add metaclasses and stir to taste ;-)

Regards,
Bengt Richter
Aug 4 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by Stephan Diehl | last post: by
3 posts views Thread by Mike C. Fletcher | last post: by
2 posts views Thread by Santiago Aguiar | last post: by
27 posts views Thread by Michele Simionato | last post: by
4 posts views Thread by Michael Sparks | last post: by
13 posts views Thread by Jean-François Doyon | last post: by
9 posts views Thread by Steffen Glückselig | last post: by
10 posts views Thread by telesphore4 | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.