2013-04-24 43 views
1

这可能是一个超级结点的问题,道歉。我试图在PHP中实现一种效果,我从PHP中获得了这种效果,PHP正在为私有属性构建getter和setter函数。Python 2.7版:如何建立的getter/setter函数访问类不继承属性?

在PHP中我通常会做这样的事情:

<?php 
class newClass() { 
    private $var = null; 

    function newClass($initVal) { 
     //init 
    } 

    public function get($var) { 
     if (isset($this->$var)) { 
      return $this->$var; 
     } 
    } 
} 
?> 

但是,试图在Python同样的想法:

class newClass(): 
    def __init__(self, initVal): 
     self.__nameOfVar1 = initVal 
     self.__nameOfVar2 = initVal 


    def get(self, var): 
       #assuming, when called, var = nameOfVar1 
     if self.__var: 
      return self.__var 

抛出Error AttributeError:'newClass' object has no attribute '__var'

也是理所当然的,它没有。如何构建getter和setter函数来访问私有属性?


UPDATE:

我已经离开了原来的问题,因为它似乎对新来Python的学习,​​他们可能会不小心将带来其约定从其他语言了一些有益的。但实际上,我最初的问题有点不同,试图让这个问题更笼统,我混淆了我的实际需要。因此,这里的修正案:

其实我不是用私有属性的工作;实际上,我正在试图通过构图环境向下传递属性。即:

Class A作为一个属性,有一个Class B对象不会从Class A继承。这几乎是从来没有的情况下Class B需要从Class A的任何信息,但在我的项目有一个情况,其中,如果用户选择不提供信息给Class B,有可能使得最后努力来推断一个合理的解决方案的声明,但是它需要来自Class A的信息,通常它不需要。

我可以建立Class B总是有这样的信息,但这意味着我几乎总是浪费时间和记忆(尽管它可能是微不足道的)。为了使这个具体的,想象一下:

toothbrushbristles,并bristles可以提供用户提供一个最佳的刷牙体验,打造了一批适合于任何一个“软”或“公司”刷毛的。但是,如果用户不提供这一点,那么我想bristlesbrush它的表面积,使其能够猜测的平均数应该是什么。

我想出了这一点,虽然我有直观的感觉,Python程序员会恨我吧;我只是想明白为什么:

@staticmethod 
def request(self, var): 
    appIndex = self.__dict__ 
    if appIndex[var]: 
     return appIndex[var] 

print Class.request(instance, var) 

工程就像一个魅力,但我认为这是Python的异端。 为什么?

+1

在做这件事之前,你应该问自己两个问题:1)你为什么使用私有属性? 2)你为什么使用getter/setter函数?这两个都不是Pythonic,通常有更好的方法来完成Python中的任务。第三个问题是,不是检查是否设置了变量,而是应该始终将其初始设置为某个默认值,然后检查该变量而不是检查它是否“已设置”。 – BrenBarn 2013-04-24 19:39:16

+3

不,它不会;这段代码会抛出一个'SyntaxError',因为'__init__'没有'def'。即使在那里,'__var'也不会抛出一个属性错误,因为它是像引用一样的[mangled](http://docs.python.org/2/reference/expressions.html#atom-identifiers)在'__init__'中。 – 2013-04-24 19:39:36

+0

请注意,在python中没有真正的私有变量...... – 2013-04-24 19:44:05

回答

9

什么您正在寻找是properties

class Foo(): 
    def __init__(self): 
     self._spam = 0 

    @property 
    def spam(self): 
     print("in the getter: ") 
     return self._spam 

    @spam.setter 
    def spam(self, move): 
     print("in the setter: ") 
     self._spam = move + self._spam 

f = Foo() 
f.spam = 2 
print(f.spam) 

输出:

in the setter: 
in the getter: 
2 
+0

啊。我懂了。感谢您不只是说我现在正在意识到您应该说的,即“阅读如何在python中完成面向对象的编程”。非常感谢,哈哈。 – Jonline 2013-04-24 19:40:47

+0

@Jonline:“在Python中如何进行面向对象的编程”是数据属性是对象接口的一部分。除非绝对必要,否则不要使用getter和setter。当它需要时,使用'@ property'从接口中隐藏getter和setter。如果你从这里学到的教训是“我应该通过使用@属性来为每个属性构建getter和setter”,那么你就是在尽可能做错事情。 – abarnert 2013-04-24 20:12:12

+0

@abarnert谢谢,这是我非常感谢的那种建议。我做了一个基于私有属性的例子,因为它似乎(当时!)更有可能是普遍有用的。实际上,我真正的问题是构建一个函数,允许没有共享继承的兄弟类(除了作为对象)在对象之间请求(在_rare_ occasion上)属性。你能指出一个你推荐学习Py的OOP约定的资源吗? – Jonline 2013-04-25 14:49:32

-1

嗯,首先,Python没有私有变量。你所指的是名称修改。目的是防止在导入模块时发生名称冲突。每当你在一个有两个ununderscore的类中写一个变量时,类的名字就会被添加到它的前面。因此,将变量“__var__”命名为python“private”事物的自定义会更明智。然而,另一方面,在python中,如果你想让一些变量能够设置和获取一个变量,通常只允许直接访问(与Java或其他语言不同)是最有意义的。

+1

“'__magic__'”名字被保留用于实现(Python实现)。对于“私人”的pythonic命名约定(如“没有你的担心,保证无效如果开封”)属性是'_single_leading_underscore' – 2013-04-24 20:04:37

+0

好吧。我想我没有在那里作出区分,但这是一个很好的做法。 – 2013-04-24 23:54:04