using metaclass __call__ to replace class instance

  • Thread starter Ksenia Marasanova
  • Start date
K

Ksenia Marasanova

Hi all,

I am creating some library, and want use "declarative" style in the
subclasses as much as possible, while the actual use will be more
method-like.

Just to give an impression, the library would be something like this:

class Baseclass(object):
# lot's of code goes here...

class Basemethod(object):
foo = None
def get_foo(cls):
return cls.foo
get_foo = classmethod(get_foo)

The subclasses:

class Class(Baseclass):

class method1(Basemethod):
foo = "foo1"

class method2(Basemethod):
foo = "foo2"


And the actual use would be:

print Class.method1()
"foo1"

print Class.method2()
"foo2"

So I thought that the way to accomplish it would be using metaclass
__call__ method:

class BasemethodMeta(type):
def __new__(cls, class_name, bases, new_attrs):
cls = type.__new__(cls, class_name, bases, new_attrs)
new_attrs['__metaclass__'].cls = cls
return cls

def __call__(self):
return self.cls.get_foo()

class Basemethod(object):
__metaclass__ = BasemethodMeta
def get_foo(cls):
return cls.foo
get_foo = classmethod(get_foo)


But it doesn't work as I expected:

print Class.method1()
"foo2"
print Class.method2()
"foo2"

I understand now that because BasemethodMeta is *type* (not sure if
this is the right word) for all Basemethod classes, it always
returnes the latest declared class... Creating dictionary and putting
all classes in it doesn't make much sense either, because
BasemethodMeta still doesn't know what is the current class that is
being called... (right?)
Now I am stuck. Can anybody show me the light?

Appreciate any help,
 
P

Peter Otten

Ksenia said:
class BasemethodMeta(type):
def __new__(cls, class_name, bases, new_attrs):
cls = type.__new__(cls, class_name, bases, new_attrs)
new_attrs['__metaclass__'].cls = cls
return cls

def __call__(self):
return self.cls.get_foo()

Though I'm not sure what you are trying to do, I fear it will get more
complicated than necessary. But you do get the desired output if
you change your metaclass to

class BasemethodMeta(type):
def __call__(cls):
# the instance of the metaclass already is a class
# so you can drop the double indirection
return cls.get_foo()

Peter
 
K

Ksenia Marasanova

2005/9/9 said:
Ksenia said:
class BasemethodMeta(type):
def__new__(cls,class_name,bases,new_attrs):
cls=type.__new__(cls,class_name,bases,new_attrs)
new_attrs['__metaclass__'].cls=cls
returncls

def__call__(self):
returnself.cls.get_foo()

Though I'm not sure what you are trying to do, I fear it will get more
complicated than necessary. But you do get the desired output if
you change your metaclass to

class BasemethodMeta(type):
def __call__(cls):
# the instance of the metaclass already is a class
# so you can drop the double indirection
return cls.get_foo()

Peter


Man.. that's easy. Thanks a lot, Peter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top