2011-08-19 19 views
5

usando Python, se puede establecer un atributo de un ejemplo a través de cualquiera de los dos métodos siguientes:¿Cómo asigno una propiedad a una instancia en Python?

>>> class Foo(object): 
    pass 

>>> a = Foo() 
>>> a.x = 1 
>>> a.x 
1 
>>> setattr(a, 'b', 2) 
>>> a.b 
2 

También se puede asignar propiedades a través del decorador propiedad.

>>> class Bar(object): 
    @property 
    def x(self): 
     return 0 


>>> a = Bar() 
>>> a.x 
0 

Mi pregunta es, ¿cómo puedo asignar una propiedad a una instancia?

Mi intuición era intentar algo como esto ...

>>> class Doo(object): 
    pass 

>>> a = Doo() 
>>> def k(): 
    return 0 

>>> a.m = property(k) 
>>> a.m 
<property object at 0x0380F540> 

... pero, consigo este inmueble objeto extraño. Experimentos similares arrojaron resultados similares. Supongo que las propiedades están más relacionadas con las clases que con las instancias en cierto sentido, pero no conozco el funcionamiento interno lo suficientemente bien como para entender lo que está sucediendo aquí.

Respuesta

4

Es posible añadir dinámicamente las propiedades de una clase después de que ya ha creado:

class Bar(object): 
    def x(self): 
     return 0 

setattr(Bar, 'x', property(Bar.x)) 

print Bar.x 
# <property object at 0x04D37270> 
print Bar().x 
# 0 

Sin embargo, no se puede establecer una propiedad en una instancia, sólo en una clase. Puede utilizar una instancia de hacerlo:

class Bar(object): 
    def x(self): 
     return 0 

bar = Bar() 

setattr(bar.__class__, 'x', property(bar.__class__.x)) 

print Bar.x 
# <property object at 0x04D306F0> 
print bar.x 
# 0 

Ver How to add property to a class dynamically? para más información.

+1

Estoy bastante seguro de que necesitan que esto sea por instancia. Lo que propones afectaría todas las instancias. –

+0

Argh! ¡1 minuto antes que yo! :) +1 – rubik

+2

@Ross - Lo sé, dice eso en la respuesta. Simplemente no es posible agregar una propiedad a una instancia. Ver el hilo que he vinculado. – agf

1

Puede asignar la propiedad directamente a la clase de objeto:

>>> class Foo(object): 
    pass  
>>> a = Foo() 
>>> a.__class__ 
__main__.Foo  
>>> setattr(a.__class__, 'm', property(lambda self: 0)) 
>>> a.m 
0 
>>> a.m = 24 
AttributeError: can't set attribute 
2

propiedades de uso descriptors que sólo funciona en clases y por lo tanto para todas las instancias. Pero podría usar una combinación de un descriptor en una clase que consultaría una función por instancia.

>>> class Foo(object): 
...  @property 
...  def x(self): 
...   if 'x' in self.__dict__: 
...    return self.__dict__['x'](self) 
... 
>>> a = Foo() 
>>> def k(self): 
...  return 0 
... 
>>> a.__dict__['x'] = k 
>>> a.x 
0 
Cuestiones relacionadas