una - python: cómo referirse a la clase desde dentro(como la función recursiva)
sumar elementos de una matriz python (10)
Para una función recursiva podemos hacer:
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)
# ...
¿Qué quieres lograr? Es posible acceder a una clase para modificar su definición utilizando una metaclase, pero no se recomienda.
Su ejemplo de código se puede escribir simplemente como:
class A(object):
pass
some_func(A)
En Python no puedes hacer referencia a la clase en el cuerpo de la clase, aunque en lenguajes como Ruby puedes hacerlo.
En Python, en cambio, puedes usar un decorador de clase, pero se llamará una vez que la clase se haya inicializado. Otra forma podría ser usar metaclase, pero depende de lo que estés tratando de lograr.
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 que será si se define en el nivel superior. (En otros casos, probablemente no, debido a las peculiaridades del alcance de Python).
Para una ilustración del alcance del intento, intente 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 quejará de que no se haya definido el nombre global ''Bar'').
Además, algo me dice que es posible que desee consultar los métodos de clase: los documentos sobre la función de método de clase (que se utilizará como decorador), una pregunta SO relevante . Edit: Ok, entonces esta sugerencia puede no ser apropiada en absoluto ... Es solo que lo primero que pensé al leer tu pregunta fue en cosas como constructores alternativos, etc. Si algo más simple se adapta a tus necesidades, @classmethod
rareza de @classmethod
. :-)
La mayoría del código de la clase estará dentro de las definiciones de métodos, en cuyo caso simplemente puede usar el nombre A
No Funciona en una función porque los contenidos de la función se ejecutan en el momento de la llamada. Pero los contenidos de la clase se ejecutan en el momento de la definición, momento en el que la clase aún no existe.
Normalmente, no es un problema porque puede piratear más miembros en la clase después de definirlos, por lo que puede dividir 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
Sin embargo, es bastante inusual querer llamar a una función en la clase en medio de su propia definición. No está claro qué intentas hacer, pero es probable que estés mejor con los decorators (o los decoradores de clase relativamente nuevos).
No hay una manera de hacerlo dentro del alcance de la clase, a menos que A se haya definido para que sea otra cosa primero (y luego some_func (A) hará algo completamente diferente de lo que usted espera)
A menos que esté haciendo algún tipo de inspección de pila para agregar bits a la clase, parece extraño por qué querría hacer eso. ¿Por qué no solo?
class A:
# do something
pass
some_func(A)
Es decir, ejecute some_func en A después de que se haya realizado. Alternativamente, puedes usar un decorador de clase (sintaxis para esto fue agregado en 2.6) o metaclase si quisieras modificar la clase A de alguna manera. ¿Podrías aclarar tu caso de uso?
No puede con la sintaxis específica que describe debido al momento en que se evalúan. La razón por la que funciona la función de ejemplo dada es que la llamada a f (i-1) dentro del cuerpo de la función es porque la resolución del nombre de f no se realiza hasta que la función es realmente llamada. En este punto, f existe dentro del alcance de ejecución ya que la función ya ha sido evaluada. En el caso del ejemplo de clase, la referencia al nombre de la clase se busca mientras la definición de la clase aún se está evaluando. Como tal, aún no existe en el ámbito local.
Alternativamente, el comportamiento deseado se puede lograr usando una metaclase como:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Usando este enfoque, puede realizar operaciones arbitrarias en el objeto de clase en el momento en que se evalúa la clase.
Si desea referirse al mismo objeto, simplemente use ''self'':
class A:
def some_func(self):
another_func(self)
Si desea crear un nuevo objeto de la misma clase, simplemente hágalo:
class A:
def some_func(self):
foo = A()
Si desea tener acceso al objeto de la clase de metaclase (lo más probable es que no sea lo que quiere), de nuevo, simplemente hágalo:
class A:
def some_func(self):
another_func(A) # note that it reads A, not A()
Si el objetivo es llamar a la función some_func
con la clase como argumento, una respuesta es declarar some_func
como decorador de la clase. Tenga en cuenta que se llama al decorador de clase después de que se inicializa la clase. Se pasará la clase que se está decorando como argumento.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don''t forget to return the class
@some_func
class A:
x = 1
Si desea pasar argumentos adicionales a some_func
, debe devolver una función del decorador:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
@some_other_func("Hello", " and goodbye!")
class B:
x = 2
Los decoradores de clase se pueden componer, lo que hace que se llamen en el orden inverso al que se declaran:
@some_func
@some_other_func("Hello", "and goodbye!")
class C:
x = 42
El resultado de lo cual es:
# Hello C and goodbye!
# The answer is 42
Si quieres hacer un poco de piratería, hazlo.
class A(object):
...
some_func(A)
Si quieres hacer algo más sofisticado puedes usar 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 por defecto Las instancias de 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 .