¿Cómo python identificador genérico/tipo de plantilla de los escenarios? Supongamos que queremos crear un archivo externo «BinaryTree.py» y tienen que manejar árboles binarios, pero para cualquier tipo de datos.

Así que me podría pasar es el tipo de un objeto personalizado y tener un árbol binario de ese objeto. Cómo es que esta hecho en python?

  • python dispone de pato plantillas
InformationsquelleAutor keys | 2011-07-17

8 Comentarios

  1. 59

    Python usa duck typing, por lo que no necesita una sintaxis especial para el manejo de múltiples tipos.

    Que si eres de C++ de fondo, podrás recordar que, mientras las operaciones utilizadas en la plantilla de función/clase se definen en algún tipo T (en la sintaxis de nivel), puede utilizar ese tipo de T en la plantilla.

    Así que, básicamente, funciona de la misma manera:

    1. definir un contrato para el tipo de elementos que desea insertar en el árbol binario.
    2. documento de este contrato (por ejemplo, en la documentación de clase)
    3. implementar el árbol binario utilizando sólo las operaciones especificadas en el contrato
    4. disfrutar de

    Tenga en cuenta sin embargo, que a menos que escribir explícita tipo de control (que es generalmente desaconsejado), usted no será capaz de exigir que un árbol binario contiene sólo los elementos del tipo elegido.

    • André, me gustaría entender por qué explícita la comprobación de tipo normalmente se desanime en Python. Estoy confundido porque parece ser que con una dinámica de lenguaje escrito, la que podría obtener en un montón de problemas si no podemos garantizar los posibles tipos que entran en la función. Pero, de nuevo, soy muy nuevo en Python. 🙂
    • Usted puede tener implícito el tipo de comprobación con tipo de sugerencias en PEP 484 y un comprobador de tipos
    • usted no debería comprobar los tipos, ya que python es pato escribió. Si alguien quiere usar su funcionalidad con una clase diferente, que depende de ellos, siempre y cuando pasen las cosas que se comportan igual que los patos, no importa si es en realidad un pato, o un falso pato.
    • En Python purista de la perspectiva, Python es un lenguaje dinámico y duck-typing es el paradigma; es decir, el tipo de seguridad es gobernado ‘no-Python’. Esto es algo que fue difícil para mí encontrar aceptable – por un tiempo – como estoy muy creados en C#. Por un lado, me parece el tipo de seguridad de una necesidad. Como me han equilibrado la balanza entre el .Net mundial y el Python el paradigma, he aceptado que tipo de seguridad es realmente un chupete y si necesito, todo lo que tengo que hacer es if isintance(o, t): o if not isinstance(o, t): … bastante simple.
    • Gracias comentaristas, los grandes respuestas. Me di cuenta después de la lectura de los mismos que, en realidad, yo sólo quiero el tipo de comprobación para la captura de mis propios errores. Así que me limitaré a utilizar implícita la comprobación de tipos.
    • Para la última parte «You'll note however, that unless you write explicit type checking (which is usually discouraged), you won't be able to enforce that a binary tree contains only elements of the chosen type.» uno puede assert aquí para tipos específicos. Esto es lo que hago a menudo y es mucho más fácil para el tipo de al lado para averiguar la voluntad de este método de clase o de trabajo para él.

  2. 16

    Realidad ahora usted puede utilizar los genéricos en Python 3.5+.
    Ver PEP-484 y escribir la documentación de la biblioteca.

    Según mi práctica no es muy fluida y clara, especialmente para aquellos que están familiarizados con Java Generics, pero aún utilizable.

    • Que se parece a un hoteles de rip-off de genéricos tbh. Es como que alguien se genéricos, ponerlos en una licuadora, dejar que se ejecute y se olvidó de ella hasta que la licuadora motor quemado, y luego se llevó a cabo 2 días más tarde y dijo: «hey, tenemos genéricos».
  3. 8

    Después de algunos buenos pensamientos en la fabricación de los tipos genéricos en python, empecé a buscar otros que tenían la misma idea, pero no pude encontrar ninguna. Así que, aquí está. Lo probé y funciona bien. Nos permite parametrizar nuestros tipos en python.

    class List( type ):
    
            def __new__( type_ref, member_type ):
    
                class List( list ):
    
                    def append( self, member ):
    
                        if not isinstance( member, member_type ):
                            raise TypeError( 'Attempted to append a "{0}" to a "{1}" which only takes a "{2}"'.format(
                                type( member ).__name__,
                                type( self ).__name__,
                                member_type.__name__ ) )
    
                        list.append( self, member )
    
                return List 

    Ahora puede derivar tipos de este tipo genérico.

    class TestMember:
            pass
    
    class TestList( List( TestMember ) ):
    
        def __init__( self ):
            super().__init__()
    
    
    test_list = TestList()
    test_list.append( TestMember() )
    test_list.append( 'test' ) # This line will raise an exception

    Esta solución es simplista, y que tiene sus limitaciones. Cada vez que se crea un tipo genérico, se creará un nuevo tipo. Por lo tanto, múltiples clases que heredan List( str ) como padre sería heredar de dos clases distintas. Para superar esto, usted necesita para crear un diccionario para almacenar las distintas formas de la clase interna y volver a la anterior creado interior de la clase, en lugar de crear uno nuevo. Esto podría evitar la duplicación de tipos con los mismos parámetros que se va a crear. Si está interesado, una solución más elegante puede ser hecho con decoradores y/o metaclasses.

    • ¿Puede explicar cómo el diccionario puede ser utilizado en el ejemplo anterior? ¿Tienes un fragmento de código para que sea en git o algo? Gracias..
    • No tengo un ejemplo, y que podría ser un poco mucho tiempo ahora. Sin embargo, los principios no son tan difíciles. El dict actúa como caché. Cuando la nueva clase es crear, se debe tener en cuenta el tipo de parámetros para crear un identificador para que el tipo y la configuración del parámetro. A continuación, se puede utilizar como una clave en un diccionario para buscar las previamente existentes de clase. De esta manera, se va a utilizar una clase una y otra vez.
  4. 3

    Dado que python es dinámicamente tipado, esto es muy fácil. De hecho, usted tendría que hacer trabajo extra para su BinaryTree clase no trabajar con cualquier tipo de datos.

    Por ejemplo, si desea que los valores de clave que se utilizan para colocar el objeto en el árbol disponible dentro del objeto a partir de un método como key() usted acaba de llamar key() en los objetos. Por ejemplo:

    class BinaryTree(object):
    
        def insert(self, object_to_insert):
            key = object_to_insert.key()

    Nota que usted nunca tendrá que definir qué tipo de clase object_to_insert es. Tanto tiempo como el que tiene un key() método, va a trabajar.

    La excepción es si lo quieres para trabajar con tipos de datos básicos como cadenas o enteros. Tendrás que envolver en una clase para hacerlos funcionar con su genérico BinaryTree. Si eso suena demasiado de peso pesado y desea que el extra de la eficiencia de la realidad, almacenar cadenas de caracteres, lo siento, eso no es lo que Python es bueno.

    • Por el contrario: todos los tipos de datos son objetos en Python. Ellos no necesitan ser envuelto (como en Java con Integer boxing/unboxing).
  5. 2

    Porque Python es dinámicamente tipado, los tipos de los objetos no importa en muchos casos. Es una mejor idea para aceptar cualquier cosa.

    Para demostrar lo que quiero decir, esta clase de árbol aceptará cualquier cosa por sus dos ramas:

    class BinaryTree:
        def __init__(self, left, right):
            self.left, self.right = left, right

    Y podría ser utilizado como esta:

    branch1 = BinaryTree(1,2)
    myitem = MyClass()
    branch2 = BinaryTree(myitem, None)
    tree = BinaryTree(branch1, branch2)
    • Los tipos de objetos hacer de la materia. Si eres un bucle sobre los elementos del contenedor y se llama a un método foo en cada objeto, y luego poner las cadenas en el contenedor es una mala idea. No es un mejores idea de aceptar algo. Sin embargo, es práctica a no exigir que todos los objetos en el contenedor se derivan de la clase HasAFooMethod.
    • En realidad, el tipo de no asunto: se tiene a pedido.
    • Oh, OK. No he entendido entonces.
  6. 1

    Un vistazo a cómo el construido-en envases de hacerlo. dict y list y así sucesivamente contienen elementos heterogéneos de cualquier tipo que te gusta. Si se define, por ejemplo, un insert(val) función de su árbol, en algún punto de hacer algo como node.value = val y Python se encargará del resto.

  7. 1

    Si el uso de Python 2 o quieres volver a escribir el código java. Su no es real solución para esto. Aquí es lo que me toca trabajar en una noche: https://github.com/FlorianSteenbuck/python-generics yo aún no compilador para usted utiliza actualmente como que:

    class A(GenericObject):
        def __init__(self, *args, **kwargs):
            GenericObject.__init__(self, [
                ['b',extends,int],
                ['a',extends,str],
                [0,extends,bool],
                ['T',extends,float]
            ], *args, **kwargs)
    
        def _init(self, c, a, b):
            print "success c="+str(c)+" a="+str(a)+" b="+str(b)

    TODOs

    • Compilador
    • Obtener Genérico Clases y Tipos de trabajo (Por cosas como <? extends List<Number>>)
    • Agregar super apoyo
    • Agregar ? apoyo
    • Código De Limpiar

Dejar respuesta

Please enter your comment!
Please enter your name here