2010-01-09 15 views
14

Para una función recursiva que podemos hacer:pitón: cómo hacer referencia a la clase de dentro de ella (como la función recursiva)

def f(i): 
    if i<0: return 
    print i 
    f(i-1) 

f(10) 

Sin embargo hay una manera de hacer lo siguiente?

class A: 
    # do something 
    some_func(A) 
    # ... 
+1

No está claro lo que quiere o quiere decir. 'clase A:' no crea un objeto, por lo que no hay 'A' para referirse. Vea las soluciones presentadas para las posibles cosas que podría haber querido decir ... –

+8

@Andrew __class A: __ crea un _class object_ como las clases en python son de primera clase –

Respuesta

4

Si se desea hacer referencia al mismo objeto, sólo tiene que utilizar 'yo':

class A: 
    def some_func(self): 
     another_func(self) 

Si desea crear un nuevo objeto de la misma clase, sólo lo hacen:

class A: 
    def some_func(self): 
     foo = A() 

Si desea tener acceso a la metaclase objeto de clase (lo más probable es que no lo que quiere), de nuevo, sólo lo hacen:

class A: 
    def some_func(self): 
     another_func(A) # note that it reads A, not A() 
+2

Solo una aclaración: en su último ejemplo, refiriéndose a "A" se conoce como el "objeto de clase", no una "metaclase", que es un concepto completamente diferente. La metaclase de A en tu ejemplo sería 'tipos.ClassType' (o 'tipo' si usa clases de estilo nuevo o python3) – Crast

-1

La mayoría del código de la clase estará dentro de las definiciones de métodos, en cuyo caso puede simplemente usar el nombre A.

+1

-1 Se está preguntando específicamente sobre llamar a A en el cuerpo principal de la clase, no desde sus métodos. –

0

¿Qué desea lograr? Es posible acceder a una clase para modificar su definición utilizando una metaclase, pero no es recomendable.

Su ejemplo de código puede escribirse simplemente como:

class A(object): 
    pass 
some_func(A) 
1

No hay una manera de hacerlo dentro del ámbito de la clase, no menos que A se define para ser otra cosa primero (y luego some_func (A) hará algo completamente diferente de lo que espera)

A menos que esté haciendo algún tipo de inspección de la pila para agregar bits a la clase, parece extraño por qué querría hacer eso. ¿Por qué no simplemente:

class A: 
    # do something 
    pass 

some_func(A) 

Es decir, ejecute some_func en A después de que se haya realizado. Alternativamente, podría usar un decorador de clase (se agregó la sintaxis en 2.6) o una metaclase si desea modificar la clase A de alguna manera. ¿Podría aclarar su caso de uso?

0

No. Funciona en una función porque los contenidos de la función se ejecutan en el tiempo de llamada. Pero los contenidos de la clase se ejecutan a la hora de definición, momento en el que la clase aún no existe.

¡No es normalmente un problema porque se puede cortar más miembros en la clase después de definirlo, por lo que puede dividirse una definición de clase en varias partes:

class A(object): 
    spam= 1 

some_func(A) 

A.eggs= 2 

def _A_scramble(self): 
    self.spam=self.eggs= 0 
A.scramble= _A_scramble 

Es, sin embargo, bastante inusual para querer llamar a una función en la clase en el medio de su propia definición. No está claro lo que estás tratando de hacer, pero es probable que estés mejor con decorators (o el relativamente nuevo class decorators).

0

Está bien hacer referencia al nombre de la clase dentro de su cuerpo (como dentro de las definiciones de métodos) si está realmente dentro del alcance ... Lo cual será si está definido en el nivel superior. (En otros casos, probablemente no, debido a las peculiaridades del alcance de Python).

Para el ejemplo de la Gotcha alcance, tratan de crear una instancia de Foo:

class Foo(object): 
    class Bar(object): 
     def __init__(self): 
      self.baz = Bar.baz 
     baz = 15 
    def __init__(self): 
     self.bar = Foo.Bar() 

(. Se va a quejarse por el nombre global 'Bar' no está definido)


Además, algo me dice que es posible que desee buscar en los métodos de clase: docs on the classmethod function (para ser utilizado como decorador), a relevant SO question. Edit: Ok, entonces esta sugerencia puede no ser apropiada en absoluto ... Es solo que lo primero que pensé al leer su pregunta fue cosas como constructores alternativos, etc. Si algo más simple se ajusta a sus necesidades, manténgase alejado de @classmethod rareza . :-)

5

No puede hacerlo con la sintaxis específica que está describiendo debido a la hora en que se evalúan. El motivo por el que funciona la función de ejemplo dada es que la llamada a f (i-1) dentro del cuerpo de la función se debe a que la resolución de nombre f no se realiza hasta que realmente se llama a la función. En este punto f existe en el ámbito de ejecución ya que la función ya ha sido evaluada. En el caso del ejemplo de la clase, la referencia al nombre de la clase se busca durante la evaluación de la clase todavía se está evaluando. Como tal, todavía no existe en el ámbito local.

Alternativamente, el comportamiento deseado se puede lograr usando una metaclase como tales:

class MetaA(type): 

    def __init__(cls): 
     some_func(cls) 

class A(object): 
    __metaclass__=MetaA 
    # do something 
    # ... 

uso de este enfoque puede realizar operaciones arbitrarias de la clase de objeto en el momento que se evalúa la clase.

+1

Esta es la única respuesta que explica * por qué * no se puede hacer (los cuerpos de función no se ejecutan simplemente en la definición, mientras que los cuerpos de clase son). Gracias por la aclaración. – Dubslow

1

Si usted quiere hacer sólo una pequeña cosa hacky hacer

class A(object): 
    ... 
some_func(A) 

Si usted quiere hacer algo más sofisticado puede utilizar una metaclase. Una metaclase es responsable de manipular el objeto de clase antes de que se cree completamente. Una plantilla sería:

class AType(type): 
    def __new__(meta, name, bases, dct): 
     cls = super(AType, meta).__new__(meta, name, bases, dct) 
     some_func(cls) 
     return cls 

class A(object): 
    __metaclass__ = AType 
    ... 

type es la metaclase defecto. Las instancias de las metaclases son clases, por lo que __new__ devuelve una instancia modificada de (en este caso) A.

Para obtener más información sobre las metaclases, consulte http://docs.python.org/reference/datamodel.html#customizing-class-creation.

14

En Python no puede hacer referencia a la clase en el cuerpo de la clase, aunque en idiomas como Ruby puede hacerlo.

En Python, en cambio, puede utilizar un decorador de clases, pero se llamará una vez que la clase se haya inicializado. Otra forma podría ser usar metaclass, pero depende de lo que intentes lograr.

+0

¿Por qué? ¿Qué hace que un cuerpo de definición de clase sea diferente de un cuerpo de función en ese aspecto? Dado que las funciones y las clases son objetos de primera clase, la diferencia en sus cuerpos no es inmediatamente evidente para mí. Editar: Como señala otra respuesta a continuación, los cuerpos de funciones * no * se ejecutan cuando la propia definición se ejecuta, mientras que los cuerpos de clase se ejecutan como parte de la ejecución de la definición de clase. – Dubslow

+0

¿Cómo se usan decoradores de clases y metaclases para lograr esto? Un ejemplo sería genial. –

Cuestiones relacionadas