2009-04-28 14 views
26

¿Cómo accedo a un atributo privado de una clase padre de una subclase (sin hacerlo público)?Python "protected" attributes

+4

¿Quieres decir protected, or private? Su pregunta es diferente de su título ... – unwind

+7

Dado que proteger y privado no significan mucho en Python, proporcione el código real. –

Respuesta

60

Mi comprensión de la convención de Python es

  • _member está protegido
  • __member es privado

Opciones para si el control de la clase padre

  • Que sea protegida en lugar de privado ya que parece lo que realmente quieren
  • Utilice un captador (@property def _protected_access_to_member ...) para limitar el acceso protegido

Si no lo controla

  • Deshacer el nombre mangling. Si dir (objeto) verá los nombres algo así como _Class__member que es lo que hace Python para llevar __ a "hacerlo privado". No hay verdaderamente privado en python. Esto es probablemente considerado malvado.
0

Hacer un método de acceso, a menos que me estoy perdiendo algo:

def get_private_attrib(self): 
    return self.__privateWhatever 
2

si el nombre de la variable es "__secret" y el nombre de la clase es "MyClass" se puede acceder a ella como este en una instancia denominada "var "

var._MyClass__secret

La convención para sugerir/emular las protecciones es darle un nombre con un subrayado inicial: self._protected_variable = 10

Por supuesto, cualquiera puede modificarlo si realmente lo desea.

10

Usando @property y a hacer lo que quiera

por ejemplo

class Stock(object): 

    def __init__(self, stockName): 

     # '_' is just a convention and does nothing 
     self.__stockName = stockName # private now 


    @property # when you do Stock.name, it will call this function 
    def name(self): 
     return self.__stockName 

    @name.setter # when you do Stock.name = x, it will call this function 
    def name(self, name): 
     self.__stockName = name 

if __name__ == "__main__": 
     myStock = Stock("stock111") 

     myStock.__stockName # It is private. You can't access it. 

     #Now you can myStock.name 
     N = float(raw_input("input to your stock: " + str(myStock.name)+" ? ")) 
+5

La pregunta era sobre el acceso al atributo en una subclase. –

+1

Modifiqué tu ejemplo un poco. Vea abajo. – user1928764

22

Dos filosofías de protección

Algunos diseñadores del lenguaje suscribirse a la siguiente hipótesis:

"Muchos programadores son irresponsables, tontos o ambos".

Estos diseñadores del lenguaje que se animan a proteger a los programadores una de la otra mediante la introducción de un especificador private a su idioma. Poco después, reconocen que esto a menudo es demasiado inflexible e introducen también protected.

Diseñadores de lenguaje como Python's Guido van Rossum, por el contrario, asumen que los programadores son adultos responsables y capaces de buen juicio (quizás no siempre, pero típicamente). Encuentran que todos deberían poder acceder a los elementos de un programa si es necesario hacerlo, para que el lenguaje no interfiera con lo correcto. (El único lenguaje de programación que se pueden conseguir con éxito en la forma de hacer el mal cosa es la NULL idioma)

Por lo tanto, _myfield en Python significa algo así como "El diseñador de este módulo está haciendo algunas cosas no evidente con este atributo, así que por favor no lo modifique y evite incluso leerlo si puede: se han proporcionado formas adecuadas de acceder a información relevante ".

En caso de que no pueda evitar el acceso al _myfield (como en casos especiales en una subclase), simplemente acceda a él.

+1

@ BobStein-VisiBone +1 para Python como humanista secular. –

+0

¿Puedes creerlo @san, la analogía ya se ha [hecho] (http://higherorderfun.com/blog/2011/02/16/if-programming-languages-were-religions/)? –

+0

@ BobStein-VisiBone gracias ... Soy humanitario entonces –

0

nadie parece responder a la pregunta original

cómo acceder a un atributo particular de una clase padre de una subclase

Así que aquí hay un caso de uso sencillo, lo que demuestra dos opciones - los padres para acceder __private variables clase y el uso de @property decorator:

class Family: 

    def __init__(self, name): 
     self.__family_name = name 

    @property 
    def name(self): 
     return self.__family_name 


class Child(Family): 

    def __init__(self, first_name, last_name): 
     super(Child, self).__init__(last_name) 
     self.__child_name = first_name 


    @property 
    def name(self): 
     return (self.__child_name, super(Child, self).name) 


if __name__ == '__main__': 
    my_child = Child("Albert", "Einstein") 

    # print (my_child.__child_name)   # AttributeError - trying to access private attribute '__child_name' 
    # print (my_child.__family_name)  # AttributeError - trying to access private attribute '__family_name' 
    print (my_child._Child__child_name)  # Prints "Albert" - By accessing __child_name of Child sub-class 
    print (my_child._Family__family_name) # Prints "Einstein" - By accessing __family_name in Family super-class 
    print (" ".join(my_child.name))   # Prints "Albert Einstein" - By using @property decorators in Child and Family 
0

creo que este código es un poco más claro que Steve. La respuesta de Steve fue de lo más útil para lo que estoy tratando de hacer, ¡así que gracias! Probé esto con python 2.7 y python 3.6.

#! /usr/bin/python 
# 
# From https://stackoverflow.com/questions/797771/python-protected-attributes 
from __future__ import print_function 
import sys 

class Stock(object): 

    def __init__(self, stockName): 

     # '_' is just a convention and does nothing 
     self.__stockName = stockName # private now 


    @property # when you do Stock.name, it will call this function 
    def name(self): 
     print("In the getter, __stockName is %s" % self.__stockName, file=sys.stderr) 
     return self.__stockName 

    @name.setter # when you do Stock.name = x, it will call this function 
    def name(self, name): 
     print("In the setter, name is %s will become %s" % (self.__stockName, name), file=sys.stderr) 
     self.__stockName = name 

if __name__ == "__main__": 
    myStock = Stock("stock111") 

    try: 
     myStock.__stockName # It is private. You can't access it. 
    except AttributeError as a: 
     print("As expect, raised AttributeError", str(a), file=sys.stderr) 
    else: 
     print("myStock.__stockName did did *not* raise an AttributeError exception") 


    #Now you can myStock.name 
    myStock.name = "Murphy" 
    N = float(input("input to your stock: " + str(myStock.name)+" ? ")) 
    print("The value of %s is %s" % (myStock.name, N)) 
Cuestiones relacionadas