如何复制python类属性?

如何复制python类属性?,python,Python,为了探索Python作为一种语言的边界,我正在探索是否有可能在信息隐藏方面比使用前导下划线表示“私有”实现细节的约定更进一步 我已经通过使用这样的代码从本地定义的类复制“public”内容,实现了字段和方法的一些额外的隐私级别: from __future__ import print_function class Dog(object): def __init__(self): class Guts(object): def __init__(

为了探索Python作为一种语言的边界,我正在探索是否有可能在信息隐藏方面比使用前导下划线表示“私有”实现细节的约定更进一步

我已经通过使用这样的代码从本地定义的类复制“public”内容,实现了字段和方法的一些额外的隐私级别:

from __future__ import print_function

class Dog(object):
    def __init__(self):
        class Guts(object):
            def __init__(self):
                self._dog_sound = "woof"
                self._repeat = 1

            def _make_sound(self):
                for _ in range(self._repeat):
                    print(self._dog_sound)

            def get_repeat(self):
                return self._repeat

            def set_repeat(self, value):
                self._repeat = value

            @property
            def repeat(self):
                return self._repeat

            @repeat.setter
            def repeat(self, value):
                self._repeat = value

            def speak(self):
                self._make_sound()

        guts = Guts()

        # Make public methods
        self.speak = guts.speak
        self.set_repeat = guts.set_repeat
        self.get_repeat = guts.get_repeat

dog = Dog()
print("Speak once:")
dog.speak()
print("Speak twice:")
dog.set_repeat(2)
dog.speak()
然而,我正在努力找到一种方法来为属性setter和getter做同样的事情

我希望能够编写如下代码:

print("Speak thrice:")
dog.repeat = 3
dog.speak()
而且它可以打印三次“woof”

我在
Dog.\uuuu init\uuuu
中尝试了以下所有方法,它们都没有爆炸,但似乎也没有任何效果:

Dog.repeat = guts.repeat
self.repeat = guts.repeat
Dog.repeat = Guts.repeat
self.repeat = Guts.repeat
self.repeat = property(Guts.repeat.getter, Guts.repeat.setter)
self.repeat = property(Guts.repeat.fget, Guts.repeat.fset)

描述符仅在类上定义时有效,而不是在实例上。阿巴内特已经指给你看了。关键的声明是:

对于对象,机器位于
对象中。
b.x
转换为
类型(b)。\uu dict\uuu['x'].\uu get\uuu(b,类型(b))

注意对
类型(b)
的引用。整个类只有一个属性对象,实例信息在访问时传入

这意味着您不能在单个
Dog
实例上拥有只处理特定狗内脏的属性。您必须在Dog类上定义一个属性,并让它通过
self
访问单个狗的内脏。除了你的设置不能这样做,因为你没有在
self
上存储对狗内脏的引用,因为你试图隐藏内脏

底线是,如果不在“外向”对象上存储对该对象的引用,就无法有效地代理对底层“guts”对象的属性访问。如果你存储了这样一个引用,人们可以用它来以“未经授权”的方式修改内脏

而且,遗憾的是,即使你现有的例子也不能真正保护你的勇气。我可以这样做:

>>> d = Dog()
>>> d.speak.__self__._repeat = 3
>>> d.speak()
woof
woof
woof

尽管您试图通过仅公开guts的公共方法来隐藏guts,但这些公共方法本身包含对实际guts对象的引用,允许任何人直接潜入并修改guts,绕过您的信息隐藏方案。这就是为什么在Python中强制执行信息隐藏是徒劳的:语言的核心部分,比如方法,已经暴露了很多东西,你不能堵住所有的漏洞。

你可以用描述符和元类建立一个系统,
Dog
元类为类的所有公共属性创建描述符,并构造一个包含所有私有方法的
SecretDog
类,然后让每个
Dog
实例都有一个影子
SecretDog
实例,该实例由容纳“私有”实现的描述符跟踪。然而,要用一种本质上不可能有任何私有内容的语言来“保护”私有实现,这将是一个非常漫长的过程。要让继承可靠地工作,您也将经历一段痛苦的时光


最后,如果您想在Python中隐藏一个私有实现,那么您可能应该将其作为C扩展来编写(或者一开始就不尝试这样做)。如果您的目标是更深入地理解该语言,那么考虑编写C扩展并不是一个不好的开始。

您需要这样的东西

>>> class hi:
...     def __setattr__(self, attr, value):
...             getattr(self, attr)(value)
...     def haha(self, val):
...             print val
...
>>> a = hi()
>>> a.haha = 10
10

小心点

你为什么要这样做?如果你想要Java,就使用Java,不要试图去解压Python。你读过这篇文章了吗?如果不是,那么就很难解释为什么你的代码不能实现你想要的,以及如何让它实现。而且,一旦你读完它,你可能会自己知道答案。@sr2222正如我所说,我正在探索Python的边界。这是我所知道的深入理解一门语言以及为什么要以某种方式使用(而不是使用)它的最好方法。@abamert是的,我以前读过,但我将回头再看一看。谢谢你的提示!