Python: Should I use a constant or property?

Which of the following two approaches is considered best practice? Both achieved the same result.

class Foo(): LABELS = ('One','Two','Three') class Bar(): def __init__(self): self.__labels = ('One','Two','Three') @property def labels(self): return self.__labels 
+4
source share
6 answers

If you do not need to customize the behavior or customization, it makes no sense to create something property. The first version is better.

In addition, they are not completely identical in their behavior. In Foo there is a class attribute for labels. There is no Bar . The link to Foo.LABELS will work fine, the link to Bar.labels will throw an exception.

+4
source

The first option reports that labels are declared in all instances of the class, ...

 class Foo(): LABELS = ('One','Two','Three') 

while the second looks like shortcuts specific to each instance. I would go with the first if the labels are constant - it is more consistent.

+1
source

The PEP 8 style guide for Python code offers a third way, and Zen of Python agrees.

They propose adding a very simple module that creates a namespace for defining constants.

 # entire of contents of eg /package/constants.py LABELS=('One', 'Two', 'Three') # example usage from package.constants import LABELS print('The labels are {0}'.format(LABELS)) # output >>> The labels are ('One', 'Two', 'Three') 

Please note that there is no obvious permanent “protection”. You can jump through hoops to try to get constant constants ... Or you can agree that any protection that you put in place can be dropped by someone who really wants, and then just repeat the quotation of who said this, about agreeing adults, and go with the very reasonable notion that variables in ALL_CAPS properly respected by developers enough that you just don't have to worry about enforcing your concept of constant.

+1
source

It depends on the scope of the variable. I use class variables as a reference to constants, just like #define SOMETHING in C. Instance variables, on the other hand, can have different values ​​for different instances. Perhaps an example will explain this better.

 class ChessBoardTile: BLACK = 'black' WHITE = 'white' def __init__(self,clr): self._color = clr t = ChessBoardTile(ChessBoardTile.BLACK) 
0
source

I made an example to convince you to take a second approach, but I got confused ...

 >>> class Foo(): ... LABELS = ('One','Two','Three') ... >>> Foo.LABELS ('One', 'Two', 'Three') >>> Foo.LABELS = (1,2,3) >>> Foo.LABELS (1, 2, 3) >>> f = Foo() >>> g = Foo() >>> f.LABELS = ('a','b','c') >>> g.LABELS (1, 2, 3) >>> Foo.LABELS (1, 2, 3) >>> f.LABELS ('a', 'b', 'c') 

"What's happening?" I thought to myself. Then I realized that the behavior depends on the identifiers of the objects ...

 >>> id(Foo.LABELS) 4562309280 >>> id(g.LABELS) 4562309280 >>> id(f.LABELS) 4562068336 >>> ('a','b','c') is ('a','b','c') False >>> Foo.LABELS = (4,5,6) >>> g.LABELS (4, 5, 6) >>> f.LABELS ('a', 'b', 'c') >>> id(Foo.LABELS) 4562309200 >>> id(g.LABELS) 4562309200 >>> id(f.LABELS) 4562068336 

So, back to my original answer: don't take the first approach unless you care if your variable is reassigned because what you get is not what you expect. The first approach makes the variable a member of the class, the second makes the variable membership of the instance, but if someone reassigns the variable in the first situation, you will get some very strange results.

Consequence If you have class methods that Foo.LABELS only to the class variable (i.e. Foo.LABELS ), then you will obviously get what you expect, but if someone reuses your code differently, then who knows What do they get?

Corollary # 2 - in python there is no way to force the use of immutable links. So you really have to go with a second approach.

0
source

Definitely the first because:

  • it conveys your intention easier and better

  • it can use less memory since the class variable is evaluated only once. While the second example creates the same over-and-over tuple, and it may not be cached (internalized).

  • and, as others have pointed out, you can request Foo.LABELS, which may be related to adding structure to your constants.

0
source

Source: https://habr.com/ru/post/1487549/


All Articles