weeCoder
weeCoder

Reputation: 268

Why is it considered bad practice to hardcode the name of a class inside that class's methods?

In python, why is it a bad thing to do something like this:

class Circle:
  pi = 3.14159 # class variable
  def __init__(self, r = 1):
    self.radius = r
  def area(self):
    return Circle.pi * squared(self.radius)

def squared(base): return pow(base, 2)

The area method could be defined as follows:

def area(self): return self.__class__.pi * squared(self.radius) 

which is, unless I'm very much mistaken, considered a better way to reference a class variable. The question is why? Intuitively, I don't like it but I don't seem to completely understand this.

Upvotes: 2

Views: 1164

Answers (4)

Versatile
Versatile

Reputation: 459

Zen of python says keep your code as simple as possible to make it readable. Why to get into using the class name or super. If you just use self then it will refer the relevant class and print its relevant variable. Refer below code.

class Rectangle(object):
    self.name = "Rectangle"
    def print_name(self):
        print(self.name)

class Square(Rectangle):
    name = 'square'

sq = Square()
sq.print_name

Upvotes: 0

user2357112
user2357112

Reputation: 281949

Why is it considered bad practice to hardcode the name of a class inside that class's methods?

It's not. I don't know why you think it is.

There are plenty of good reasons to hardcode the name of a class inside its methods. For example, using super on Python 2:

super(ClassName, self).whatever()

People often try to replace this with super(self.__class__, self).whatever(), and they are dead wrong to do so. The first argument must be the actual class the super call occurs in, not self.__class__, or the lookup will find the wrong method.

Another reason to hardcode the class name is to avoid overrides. For example, say you've implemented one method using another, as follows:

class Foo(object):
    def big_complicated_calculation(self):
        return # some horrible mess
    def slightly_different_calculation(self):
        return self.big_complicated_calculation() + 2

If you want slightly_different_calculation to be independent of overrides of big_complicated_calculation, you can explicitly refer to Foo.big_complicated_calculation:

def slightly_different_calculation(self):
    return Foo.big_complicated_calculation(self) + 2

Even when you do want to pick up overrides, it's usually better to change ClassName.whatever to self.whatever instead of self.__class__.whatever.

Upvotes: 2

phi
phi

Reputation: 11754

I can name here two reasons

Inheritance

class WeirdCircle(Circle):
    pi = 4

c = WeirdCircle()
print(c.area()) 
# returning 4 with self.__class__.pi 
# and 3.14159 with Circle.pi

When you want to rename the class, there is only one spot to modify.

Upvotes: 2

sarnthil
sarnthil

Reputation: 405

Because in case you subclass the class it will no longer refer to the class, but its parent. In your case it really doesn't make a difference, but in many cases it does:

class Rectangle(object):
    name = "Rectangle"
    def print_name(self):
        print(self.__class__.name) # or print(type(self).name)

class Square(Rectangle):
    name = "Square"

If you instantiate Square and then call its print_name method, it'll print "Square". If you'd use Rectangle.name instead of self.__class__.name (or type(self).name), it'd print "Rectangle".

Upvotes: 4

Related Questions