Gnijuohz
Gnijuohz

Reputation: 3364

Python Metaclass did not change the class when used

I found this question while i searched the usage of metaclass in python.It's a good question with a wonderful answer,See Here.But while i followed the example like this:

class UpperAttrMetaclass(type): 

    def __new__(cls, name, bases, dct):

        attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
        uppercase_attr = dict((name.upper(), value) for name, value in attrs)

        return type.__new__(cls, name, bases, uppercase_attr)
class Foo(object):
    __metaclass__=UpperAttrMetaclass
    bar = 'bip'

Then:

print(hasattr(Foo,'bar'))

I was hoping it would output False,but instead it was True It seems the metaclass didn't change anything at all. I must have made a mistake.Glad if you can point it out to me!

EDIT: I was using IDLE 3.2,to make my situation more clear.

EDIT: Thanks for all the answers.And i found a good post on this.So i post it hereMetaclass in python 2&3

Upvotes: 3

Views: 171

Answers (2)

jsbueno
jsbueno

Reputation: 110146

As for @Irfy answer - in Python 3 the way to set a metaclass is to pass it as if it where a named-parameter in the class declaration - in your case, the code should be:

class UpperAttrMetaclass(type): 

    def __new__(cls, name, bases, dct):

        attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
        uppercase_attr = dict((name.upper(), value) for name, value in attrs)

        return type.__new__(cls, name, bases, uppercase_attr)

class Foo(metaclass=UpperAttrMetaclass):
    bar = 'bip'

(In Python 3, there is no need to inherit from object as well)

Also, just use "dir" to check the class attributes, as in dir(Foo) . No need to be inspecting attribute by attribute with "hasattr" when you can see them all.

Upvotes: 3

Irfy
Irfy

Reputation: 9587

You made no mistake. print(hasattr(Foo,'bar')) and print dir(Foo) give me:

False
['BAR', '__class__', ...

What's your Python version? Mine is 2.7.2

If you use Python 3.x, try removing the __metaclass__ attribute and declaring your class as

class Foo(object, metaclass=UpperAttrMetaclass):
    ...

Upvotes: 5

Related Questions