Re: [Python-es] Impedir creación de objeto

Milton Galo Patricio Inostroza Aguilera minoztro en gmail.com
Vie Jun 12 18:28:03 CEST 2009


El 11 de junio de 2009 4:15, Chema Cortes<pych3m4 en gmail.com> escribió:
> El 10 de junio de 2009 17:29, Milton Galo Patricio Inostroza
> Aguilera<minoztro en gmail.com> escribió:
>
>> ¿Es correcto preguntar si el producto existe en la capa de
>> persistencia y dependiendo de esto retornar object.__new__ y si no
>> existe retornar un None?
>
> Según dice la documentación:
>
> - cuando __new__(cls,...) devuelve una instancia de 'cls', se invoca
> __init__ para inicializar la instancia

esos puntitos al parecer son mentirosos...ya que si le envías un
argumento más que cls tira el siguiente warning:

DeprecationWarning: object.__new__() takes no parameters

que se genera del siguiente trozo de código:

>>> class mi(object):
...    def __new__(cls, *args):
...       return object.__new__(cls,*args)
...    def __init__(self, uno):
...       print uno
...
>>> a = mi(3)


> - cuando lo que devuelve no es instancia de 'cls' entonces no se
> invoca a __init__ y tiene que inicializar la instancia por su cuenta
> (Factoría)
>
> Entiendo yo que sí que se puede hacer lo pides de devolver 'None' para
> indicar que no se ha creado el objeto. En el ejemplo que pones, Cuando
> devuelve None no se ejecutaría el método '__init__'

si!...ahora pienso como dice Hernan es mejor lanzar una exception.

>
>
>> Una clase de prueba que hice (simple) que ejemplifica mi pensamiento
>> es la siguiente:
>>
>> class Prueba(object):
>>        def __new__(cls, *args):
>>                if args[0] == 0:     # reemplazar por la llamada a la capa inferior
>>                        return None # reemplazar
>>                return object.__new__(cls)
>>        def __init__(self, nombre, ciudad):
>>                self.nombre = nombre
>>                self.ciudad = ciudad
>
>
>> La otra duda es como se puede modificar los valores de *args para
>> enviarselos cuando uno llama al método __new__?
>
> No entiendo bien dónde quieres modificar los valores de *args. Tal vez
> usando metaclases o, más simple, con un decorador.


la idea es que en el método __new__ se busque el objeto por ejemplo en
un orm y si se encuentra enviárselo al método __init__.  la idea es la
siguiente:

  1.- El programador llama al constructor de la clase Producto y le
envía el código de barra.
  2.- El método __new__ toma el código de barra y va a buscar mediante
el orm al producto con el código recibido.
  3.- Si el objeto no es encontrado --> raise Exception.
  4.- Objeto encontrado, se le envía el objeto al método __init__
     4.1.- en este punto me interesa cambiar los argumentos del
constructor ya que no quiero enviarle el código al __init__ si no que
enviarle el objeto encontrado por el orm.
5.- El método __init__ recibe el objeto sacado del orm y comienza a
llenar los atributos de instancia.
6.- fin

Tengo una aproximación con atributos de clase...pero en realidad no me
gusta mucho, ¡Pero Funciona!...:

class Producto(object):
    itsProducto = None

    def __new__(cls, *args):
        cls.itsProducto =
models.Producto.objects.get(codigo_barra=args[0])  #busco el producto
en el orm
        return object.__new__(cls)

    def __init__(self, *args):
        self.codigo_barra = self.__class__.itsProducto.codigo_barra
        self.nombre = self.__class__.itsProducto.nombre


La idea de esta clase es desacoplarse un poco del orm, ya que
posterior me gustaría utilizar esta clase quizás con sql a pelo :-) .
Es importante señalar que si es que el producto no es encontrado el
orm estomáticamente lanza una exception lo que hará fallar el método
__new__, por lo que no se construirá la instancia.  La idea de
enviarle el objeto del orm al __init__ es no ir a buscar nuevamente en
el __init__ el objeto que ya se buscó en el método __new__

Saludos,




-- 
Milton Inostroza Aguilera
------------ próxima parte ------------
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes


Más información sobre la lista de distribución Python-es