python exception descriptor readonly-attribute

python,__slots__, y "el atributo es de solo lectura"



exception descriptor (5)

Considera esto.

class SuperSafe( object ): allowed= ( "this", "that" ) def __init__( self ): self.this= None self.that= None def __setattr__( self, attr, value ): if attr not in self.allowed: raise Exception( "No such attribute: %s" % (attr,) ) super( SuperSafe, self ).__setattr__( attr, value )

Un mejor enfoque es utilizar pruebas unitarias para este tipo de verificación. Esta es una buena cantidad de gastos generales de tiempo de ejecución.

Quiero crear un objeto en python que tenga algunos atributos y quiero protegerme de usar accidentalmente el nombre de atributo incorrecto. El código es el siguiente:

class MyClass( object ) : m = None # my attribute __slots__ = ( "m" ) # ensure that object has no _m etc a = MyClass() # create one a.m = "?" # here is a PROBLEM

Pero después de ejecutar este código simple, recibo un error muy extraño:

Traceback (most recent call last): File "test.py", line 8, in <module> a.m = "?" AttributeError: ''test'' object attribute ''m'' is read-only

¿Hay algún programador inteligente que pueda dedicar un poco de su tiempo e informarme sobre los errores de "solo lectura"?


Cuando declara variables de instancia usando __slots__ , Python crea un objeto descriptor como una variable de clase con el mismo nombre. En su caso, este descriptor se sobrescribe con la variable de clase m que está definiendo en la siguiente línea:

m = None # my attribute

Esto es lo que debe hacer: No defina una variable de clase llamada m , e inicialice la variable de instancia m en el método __init__ .

class MyClass(object): __slots__ = ("m",) def __init__(self): self.m = None a = MyClass() a.m = "?"

Como nota al margen, las tuplas con elementos individuales necesitan una coma después del elemento. Ambos funcionan en su código porque __slots__ acepta una sola cadena o una secuencia / iterable de cadenas. En general, para definir una tupla que contiene el elemento 1 , use (1,) o 1, y no (1) .


Estás abusando completamente de __slots__ . Evita la creación de __dict__ para las instancias. Esto solo tiene sentido si tiene problemas de memoria con muchos objetos pequeños, porque deshacerse de __dict__ puede reducir la huella. Esta es una optimización incondicional que no es necesaria en el 99.9% de todos los casos.

Si necesita el tipo de seguridad que describió, Python realmente es el lenguaje incorrecto. Es mejor usar algo estricto como Java (en lugar de intentar escribir Java en Python).

Si no pudo averiguar por qué los atributos de clase causaron estos problemas en su código, tal vez debería pensar dos veces antes de introducir hacks de idiomas como este. Probablemente sería más sabio familiarizarse con el lenguaje primero.

Sólo para completar, aquí está el here .


__slots__ trabaja con variables de instancia, mientras que lo que tienes allí es una variable de clase. Así es como deberías hacerlo:

class MyClass( object ) : __slots__ = ( "m", ) def __init__(self): self.m = None a = MyClass() a.m = "?" # No error


class MyClass( object ) : m = None # my attribute

La m aquí es los atributos de clase, en lugar del atributo de instancia. Necesitas conectarlo con tu instancia por __init__ mismo en __init__ .