-1

I have a code like below. My requirement is to fill BagA and BagB once and only once. So, I do not have a class but have written code in a module. I have __BagA and __BagB with underscores because I do not want it to get changed from outside. I have a getter as shown using @property decorator. But it does not work.

module.py:

import csv
import sys
import threading

__BagA = list()
__BagB = dict()
__lock = threading.Lock()

@property
def BagA():
    if not __BagA:
        raise("Call Initialize() first")
    else:
        return __BagA

@property
def BagB():
    if not __BagB:
        raise("Call lookup.Initialize() first")
    else:
        return __BagB

def __get__BagA(directory):
   #logic to populate BagA
   BagA=some list

def __get__BagB(directory):
   #logic to populate BagB
   BagB=dict after processing the logic

def initialize(directory):
    __lock.acquire()

    __get__BagA(directory)
    __get__BagB(directory)

    __lock.release()

Main script:

import module

module.initialize("dir")#this works. I see all bags getting populated
#Below does not work
module.BagA #This gives an object with some fget and fset and not the value of BagA

#below works
module.__BagA

One more problem is that instead of __BagA which could still be modified from outside, I could write BagA and have @Bag.setter decorator and @BagA.deleter decorator which returns an exception saying 'you cannot modify this'.

These are also not working and I do not want to write them separately but in a single line like below because they have same behavior. Both separate and single line do not work:

@BagA.setter,@BagA.deleter
def BagA(value):
    print('cannot set or delete') #Is this possible?
martineau
  • 119,623
  • 25
  • 170
  • 301
Three-pth
  • 49
  • 1
  • 6
  • 2
    This looks like an XY Problem and you're pretty much using "module" like a Class, but without all the handy stuff that comes with it. I think you should look into the singleton design pattern. – ChatterOne Feb 05 '20 at 07:40
  • 1
    The `@property` decorator is for use on _inside_ a class, not for module-level functions. See [Can modules have properties the same way that objects can?](https://stackoverflow.com/questions/880530/can-modules-have-properties-the-same-way-that-objects-can) for a possible workaround. – martineau Feb 05 '20 at 07:45
  • Please be aware that while it is possible to protect module attributes, it is not possible to recursively protect the protection. Ultimately, if someone wants to misuse your module, they can. Are you sure a module layout is needed, as opposed to, say, singleton or regular instances? – MisterMiyagi Feb 05 '20 at 08:14

1 Answers1

1

I have __BagA and __BagB with underscores because I do not want it to get changed from outside.

  • that's not what it's for, the double underscore is a way to avoid name collisions in inheritance scenarios
  • that's not how it works, the double underscore just mangles names using a well-defined scheme, the double underscore does not make things private or protected, they're still completely public and visible to anyone who cares
  • that doesn't do anything at the module level, it's implemented at the class level

I have a getter as shown using @property decorator. But it does not work.

@property is a descriptor, it works through the attribute-resolution mechanism of classes.

Here's how you say that a symbol is "private" and shouldn't be touched in python: you prefix it with a single underscore. Then if others touch it that's their problem for being idiots or assholes.

Masklinn
  • 34,759
  • 3
  • 38
  • 57