olamundo
olamundo

Reputation: 24991

python: reference "private" variables' names in an organized way

Suppose I have a class, and I want to reference some elements in the ' __dict__ (for instance, I want to copy the dict and delete the attribute that cannot be pickled), from inside the class.

Problem is, those attributes are "private" so my code ends up looking like so

class MyClasss(object):
    def __init__(self):
          self.__prv=1
    def __getstate__(self):
          ret=self.__dict__.copy()
          del ret['_MyClass__prv']

I reference the class name explicitly in the del statement, which looks a little ugly for me. Is there something nicer? something like MyClass.getPrivateString('prv')

Of course I can implement one myself, but I would be surprised if there isn't a builtin to surpass this problem.

Upvotes: 2

Views: 826

Answers (5)

olamundo
olamundo

Reputation: 24991

At the end, I used a variant of thieger's solution

del ret["_%s__%s" % (MyClasss.__name__, "prv")]

I think this is the most robust way I can write that piece of code, aside from giving up the mangling, which might be the right thing to do, but I was asking what to do in case you actually have mangling :)

Upvotes: 1

John La Rooy
John La Rooy

Reputation: 304255

Better to use your own naming convention for those attributes, such as _prv_x, _prv_y etc. then you can use a loop to selectively remove them

class MyClasss(object):
    def __init__(self):
          self._prv_x=1
          self._prv_y=1
    def __getstate__(self):
          return dict((k,v) for k,v in vars(self).items() if not k.startswith("_prv_"))

In python2.7+

    def __getstate__(self):
          return {k:v for k,v in vars(self).items() if not k.startswith("_prv_")}

Upvotes: -1

thieger
thieger

Reputation: 146

There is no shortcut, but if you just want to avoid naming the class explicitly, you can do something like:

del ret["_%s__%s" % (self.__class__.__name__, "prv")]

Upvotes: 0

jbernadas
jbernadas

Reputation: 2600

You might try to create a copy of the object, erase its private attributes and then return its __dict__, something like:

class X:
  def __init__(self):
    self.__prv = 0

  def del_privates(self):
    del self.__prv

  def __getstate__(self):
    other = X()
    other.__dict__ = self.__dict__.copy()
    other.del_privates()
    return other.__dict__

After calling __getstate__, the returned dict will not have the __prv member, since it gets erased when other.del_privates() is called.

Upvotes: 1

Jon-Eric
Jon-Eric

Reputation: 17275

Consider using only a single underscore for private attributes. These are still considered private but do not get name mangled.

class MyClasss(object):
    def __init__(self):
          self._prv=1
    def __getstate__(self):
          ret=self.__dict__.copy()
          del ret['_prv']

Upvotes: 6

Related Questions