Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Constant Class

I was looking at the answer to this question: Is it possible to define a class constant inside an Enum?

What interested me most was the Constant class in Ethan Furman's answer.

class Constant:
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)

The question was about Python 3.4 but I'm using 2.7. In the answer Ethan sets the gravitational constant as an instance variable of the class Planet like so:

G = Constant(6.67300E-11)

My testing of this class in 2.7 shows that typing just G gives me this:

Out[49]: Constant(3)

(I set it to 3 for ease of use while testing. This looks like the __repr__ output to me, please correct me if I"m wrong.)

The value is available via G.value. However, in Ethan's answer he uses

return self.G * self.mass / (self.radius * self.radius)

This obviously only works if the value is returned vs the __repr__ output. Now if I change class Constant: to class Constant(int): then type G I still get the __repr__ output but if I type G * 4 I get 12 not the error I was getting. (TypeError: unsupported operand type(s) for *: 'instance' and 'int' )

So clearly something like the int object can output a number when called. Is there a magic method I'm missing that would allow me to do this for the Constant class? Since constants could be strings, integers, or floats I'd prefer to have 1 class that handles them all vs 3 separate classes that extend those objects.

The value is also settable via G.value. Can I lock this down so the Constant class behaves likes an actual constant? (I suspect the answer is no.)

like image 626
Gabe Spradlin Avatar asked Sep 26 '14 20:09

Gabe Spradlin


People also ask

What is a class constant Python?

Introduction to Python Class ConstantsAn unchangeable value, assiged, is called a constant. Meaning, constants are the containers that hold some information and cannot be changed further.

What is a constant class?

Class constants can be useful if you need to define some constant data within a class. A class constant is declared inside a class with the const keyword. Class constants are case-sensitive. However, it is recommended to name the constants in all uppercase letters.

What is a constant in Python?

Python Constants A constant is a special type of variable whose value cannot be changed. In Python, constants are usually declared and assigned in a module (a new file containing variables, functions, etc which is imported to the main file).

Can you declare a constant in Python?

You cannot declare a variable or value as constant in Python. Just don't change it.


1 Answers

Your class Constant should inherit from object, to be a new style Python class.

In that way Constant will be a so called descriptor. In simple terms, descriptor are a Python construct to customize the behavior of getting and setting a class attribute. They are useful when an instance of a descriptor is set as an attribute of another class.

In your example Constant is the descriptor and Planet has an attribute which is an instance of Constant. When you get the attribute G of the Planet class (self.G in you example), what you really get is what is returned by the __get__ method of the descriptor, that is the value.

Note that __get__ is invoked only when the descriptor instance is accessed by another class attribute.

So, define the class like this:

class Constant(object):
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)

Then this little example:

c = Constant(3.14)
print c

class Test:
    c = Constant(3.14)

t = Test()
print t.c

Will print:

Constant(3.14)
3.14

See that when the Constant instance is printed directly, the method __repr__ will be called, but when printed as another class attribute, __get__ will be used.

You can read more on descriptors on this great article.

like image 99
Augusto Destrero Avatar answered Nov 15 '22 04:11

Augusto Destrero