1

Here is a quick example:

class KEY(object):
    A = 'a'
    A = 'b'
    B = 'b'

Is there a way to test that 'A' has been repeatedly defined in class 'KEY' regardless of the assigned value?

5
  • This might not be exactly what you need, but most IDE's / code analyzers will point that out. Commented Dec 14, 2012 at 17:17
  • @Thomas Orozco Thanks for your suggestion, but I need runtime checks in the unit test suite. Commented Dec 14, 2012 at 17:20
  • Then maybe using a metaclass could do the trick, but I think it wouldn't. Edit: Actually, it won't. The variables have already been converted to a dictionary (and hence, duplicates have been removed) when they reach your metaclass code. Commented Dec 14, 2012 at 17:25
  • Would overriding __new__ work? or that happens even beforehand? Sorry I am not quite familier with python 'class loading' process under the hood, and I don't feel I should work on __import__. Commented Dec 14, 2012 at 17:29
  • @ThomasOrozco: actually, Python 3 does have a provision for taht use case. One can have a __prepare__ method which could make the class parsing use am ordered dict, or some other specialized mapping. Commented Dec 14, 2012 at 21:37

2 Answers 2

2

Here's an attempt at answer:

Class variables are not going to work

You can't control redefinition for these. Basically, the metaclass is what is called to create your class, and it's passed a dict of attribute => value. We could say it's "already too late".

Using instance variables

You can control what happens when you do a.b = c after class instantiation, so what you could do is:

class RedefinitionMixin(object):
    def __setattr__(self, k, v):
        if hasattr(self, k):
            raise Exception('Attribute redefinition!')
        super(RedefinitionMixin, self).__setattr__(k, v)

class KEY(RedefinitionMixin, object):
    def __init__(self):
        self.A = 'a'
        self.A = 'b'
        self.B = 'b'

This may cause some unexpected behavior if you're already overriding __setattr__ though!

Note that this is only going to work in case you actually instantiate the class.
To circumvent the issue of using an instance, you could implement a singleton pattern.


Overall, I wouldn't recommend that solution, but that's the best I can come up with now.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 for giving the reason "Class variables are not going to work", another way is through static analysis by using inspect.getSource to the class and check appearance of each variable name in the class, though you could argue that is no difference compare to pylint.
Just tried it, actualy pylint thinks that redefined class variable is a valid case.
2

If you're using Python 3, it's possible to do this cleanly using a dict subclass that only allows nonexisting keys to be set and the __prepare__ method of a metaclass. More info here. In Python 2 it's harder; I wrote a horrible hack to achieve it, with some limits.

1 Comment

I didn't know about this new method in python 3, that's a great answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.