Reputation: 268
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
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
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
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
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