pfabri
pfabri

Reputation: 1106

Is it bad practice to access a class variable through 'self'?

Doing so suits my needs but I wonder if it's considered blasphemous (or, even, un-pythonic).

Example:

class A:
    _class_specific = 1

    def __init__(self, i):
        self.instance_specific = i
        
    def get_special_sum(self):
        return self._class_specific + self.instance_specific

t = A(2)
t.get_special_sum()  #< Returns 3

Reason for doing so:

I have a class variable _ID and an instance method check(self) defined in a Base class. Child classes have their own values for _ID. The inherited check(self) method must have access to instance-specific variables as well as the _ID variable of a given genus, which it will access through self._ID

Although the above works perfectly I wonder if there is a more explicit way of doing it? ...other than leaving a glaringly obvious comment making clear what the intention is...

Upvotes: 0

Views: 110

Answers (2)

wjandrea
wjandrea

Reputation: 33107

"Bad practice" is subjective, but one thing's for sure, you can more explicitly access a class variable via type(self) or self.__class__, for example:

    def get_special_sum(self):
        return type(self)._class_specific + self.instance_specific

So you might prefer to lookup on self in cases where the variable might be defined on the instance, otherwise it's defined on the class. Maybe that's even the case you've described — you'd be the best judge of that.

As for type(self) vs self.__class__, see Difference between type(obj) and obj.__class__

Upvotes: 1

jsbueno
jsbueno

Reputation: 110516

No, there is no problem - And it even adds flexibility to your project: say, you want one specific instance of your class to have a different value for that variable, all you have to do is set it on the instance. Just add some unit tests to ensure everywhere it is used it is being read from self., and there is no drawback.

And, yes (following some of the comments on the O.P.), if you prefer to be explicit about only allowing the value to be fectched from the class, and never be set on the instance, you can do self.__class__.attribute or type(self).attribute: it is mostly a matter of taste. If self.__class__ is to be used more than once inside a method, consider assigning it to a variable in the beggining of the method: you can a lot of legibility (and even some micro optimizations): cls = self.__class__

That said, I had used the pattern of reading class values from self and using some instances with specific values, and it really feels natural, and "the right way to do it". Just take care when setting the attribute instead: self.attr = X will always set the attribute in a single instance. When setting you have to be explicit about setting it on the class!

Upvotes: 2

Related Questions