python:reference";“私人”;变量';以有组织的方式命名

python:reference";“私人”;变量';以有组织的方式命名,python,obfuscation,private,Python,Obfuscation,Private,假设我有一个类,我想从类内部引用“\uuuu dict\uuuu中的一些元素(例如,我想复制dict并删除无法pickle的属性) 问题是,这些属性是“私有”的,所以我的代码看起来是这样的 class MyClasss(object): def __init__(self): self.__prv=1 def __getstate__(self): ret=self.__dict__.copy() del ret['_M

假设我有一个类,我想从类内部引用“
\uuuu dict\uuuu
中的一些元素(例如,我想复制dict并删除无法pickle的属性)

问题是,这些属性是“私有”的,所以我的代码看起来是这样的

class MyClasss(object):
    def __init__(self):
          self.__prv=1
    def __getstate__(self):
          ret=self.__dict__.copy()
          del ret['_MyClass__prv']
我在del语句中显式引用类名,这对我来说有点难看。 有更好的吗?类似于
MyClass.getPrivateString('prv')


当然,我可以自己实现一个,但如果没有一个内置项来解决这个问题,我会感到惊讶。

考虑对私有属性只使用一个下划线。这些仍然被认为是私有的,但不会弄乱名称

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

您可以尝试创建对象的副本,擦除其私有属性,然后返回其
\uuuuu dict\uuuu
,类似于:

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__
del ret["_%s__%s" % (self.__class__.__name__, "prv")]

调用
\uuuu getstate\uuuuu
后,返回的dict将不具有
\uuuu prv
成员,因为调用
其他.del_privates()
时,它将被擦除。

没有快捷方式,但如果您只是想避免显式命名类,可以执行以下操作:

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__
del ret["_%s__%s" % (self.__class__.__name__, "prv")]

最好对这些属性使用您自己的命名约定,例如
\u prv\u x
\u prv\u y
等。然后您可以使用循环有选择地删除它们

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_"))
在python2.7中+

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

最后,我使用了thieger解决方案的一种变体

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

我认为这是我能够编写这段代码的最健壮的方法,除了放弃损坏之外,这可能是正确的做法,但我想问的是,如果你真的有损坏,该怎么办:)

谢谢,我可能会用到这个技巧。但我真的很想为我原来的问题找到答案,比如“弄脏”。)检查我的答案,我试着用另一种方式来处理“弄脏”这个名字。@noam:这不就像是要一片止痛药,这样当你们用锤子敲击自己时,疼痛会减轻一些吗@乔恩·埃里克:谢谢你的文档指针。Python中没有私有属性,正如你的惊吓语录所显示的那样。我怀疑(但不知道)双下划线篡改是为了防止无意中访问
\uuuuuuuuuuuuuuuuuuuuuu机械
属性,如
\uuuuuuuuu getstate\uuuuuuuuuu
@msw特殊属性,如
\uuuu getstate\uuuuuuuuuuu
不会被篡改。关于命名约定以及何时在名称中使用单下划线和双下划线有很多要说的。在这种情况下,我不会使用双下划线。没有内置任何内容的原因是您错误地认为
\uuu
与私有变量有关。您试图实现什么?如果不复制“private”属性,对象的副本的行为会与原始属性不同吗?呃,这个约定已经存在:一个前导下划线。@Aaron,OP需要一种方法来区分不被pickle的变量。Zope使用了同样的想法。那么为什么不使用一个前导下划线的既定约定呢?@Aaron,也许有些私有变量确实需要修改。通过这种方式,它们仍然符合使用一个前导下划线的约定,但也有一个具有特殊用途的迷你名称空间,这与子类化不同。然而,我回答了,因为OP问我怎么做。