Cory
Cory

Reputation: 15615

Is there anything wrong with defining static varaible the following way in Python?

If you have a value that doesn't change, is there anything wrong with defining it just with @property and return the value as follows:

class Circle:
   def __init__(self, radius):
      self.radius = radius

   @property
   def pi(self):
       return  3.14

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

Since PI shouldn't change and the value is static, is there anything wrong defining it with @property as shown above?

What I usually see is the following:

class Circle:
   def __init__(self, radius):
      self.radius = radius
      self.pi = 3.14

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

Upvotes: 0

Views: 83

Answers (3)

Burger King
Burger King

Reputation: 2965

If you want to be sure to make it immutable, you can define the attribute refuse to be set.

class Circle:
   _pi = 3.14

   def __init__(self, radius):
      self.radius = radius

   @property
   def pi(self):
       return _pi

   @pi.setter
   def pi(self, value):
        pass

   ...

The pi is immutable.

   c = Circle(1)
   c.pi = 5 # The intent is to make it change
   print c.pi # Output: 3.14, it still keeps origin.

Upvotes: 0

paidhima
paidhima

Reputation: 2392

The problem with using a property is this:

>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3
>>> d.pi
3

You may be able to get around this with a metaclass:

class NoSet(type):
    def __setattr__(self, name, value):
        if name == 'pi':
            raise Exception("Can't assign")
        else:
            super(NoSet, self).__setattr__(name, value)

class Circle(object):
    __metaclass__ = NoSet

    @property
    def pi(self):
        return 3.14

>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3

Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    Circle.pi = 3
  File "<pyshell#43>", line 4, in __setattr__
    raise Exception("Can't assign")
Exception: Can't assign

For usage in Python 3 change the class definition to class Circle(object, metaclass=NoSet):.

Disclaimer: I just tried this a moment ago and it seemed to work. I can't make any promises as I have not had much experience with metaclasses. I personally wouldn't do this, if only because there might be a legitimate reason for someone to change the value - if they needed more precision, for example.

Upvotes: 0

Will Angley
Will Angley

Reputation: 1394

Python programmers I know generally avoid accessor functions, unless they're actually performing computation. In this case you'd be better off with making the variable a member of the class:

class Circle:
    pi = 3.14

    def __init__(self, radius):
        self.radius = radius

    # ...

Upvotes: 2

Related Questions