privados - self python 3
Cómo averiguar la aridad de un método en Python (5)
Aquí hay otro intento de usar metaclase, ya que uso Python 2.5, pero con 2.6 puedes decorar la clase fácilmente.
La metaclase también se puede definir a nivel de módulo, por lo que funciona para todas las clases
from types import FunctionType
def arity(unboundmethod):
def _arity():
return unboundmethod.func_code.co_argcount - 1 # remove self
unboundmethod.arity = _arity
return unboundmethod
class AirtyMetaclass(type):
def __new__(meta, name, bases, attrs):
newAttrs = {}
for attributeName, attribute in attrs.items():
if type(attribute) == FunctionType:
attribute = arity(attribute)
newAttrs[attributeName] = attribute
klass = type.__new__(meta, name, bases, newAttrs)
return klass
class Foo:
__metaclass__ = AirtyMetaclass
def bar(self, bla):
pass
print Foo().bar.arity()
Me gustaría averiguar la aridad de un método en Python (el número de parámetros que recibe). Ahora mismo estoy haciendo esto:
def arity(obj, method):
return getattr(obj.__class__, method).func_code.co_argcount - 1 # remove self
class Foo:
def bar(self, bla):
pass
arity(Foo(), "bar") # => 1
Me gustaría poder lograr esto:
Foo().bar.arity() # => 1
Actualización : En este momento, la función anterior falla con los tipos integrados, cualquier ayuda sobre esto también sería apreciada:
# Traceback (most recent call last):
# File "bla.py", line 10, in <module>
# print arity(''foo'', ''split'') # =>
# File "bla.py", line 3, in arity
# return getattr(obj.__class__, method).func_code.co_argcount - 1 # remove self
# AttributeError: ''method_descriptor'' object has no attribute ''func_co
El módulo de inspect
de la biblioteca estándar de Python es tu amigo. ¡Consulta los documentos en línea ! inspect.getargspec(func)
devuelve una tupla con cuatro elementos, args, varargs, varkw, defaults
: len(args)
es la "aridad principal", pero la arity puede ser cualquier cosa desde eso hasta el infinito si tiene varargs
y / o varkw
no None
, y algunos argumentos pueden omitirse (y predeterminarse) si los defaults
no son None
. ¿Cómo convertir eso en un solo número, me gana, pero presumiblemente tienes tus ideas en el asunto? -)
Esto se aplica a las funciones codificadas en Python, pero no a las codificadas en C. Nada en la API de Python C permite que las funciones con código C (incluidas las integradas) expongan su firma para la introspección, excepto a través de su cadena de documentación (u opcionalmente a través de anotaciones en Python 3); por lo tanto, tendrá que recurrir al análisis de la cadena de documentos como última zanja si otros enfoques fallan (por supuesto, la cadena de documentos también puede faltar, en cuyo caso la función seguirá siendo un misterio).
Esta es la única forma en que puedo pensar que debería ser 100% efectivo (al menos con respecto a si la función está definida por el usuario o escrita en C) para determinar la arity (mínima) de una función. Sin embargo, debe asegurarse de que esta función no cause ningún efecto secundario y que no genere un TypeError:
from functools import partial
def arity(func):
pfunc = func
i = 0
while True:
try:
pfunc()
except TypeError:
pfunc = partial(pfunc, '''')
i += 1
else:
return i
def foo(x, y, z):
pass
def varfoo(*args):
pass
class klass(object):
def klassfoo(self):
pass
print arity(foo)
print arity(varfoo)
x = klass()
print arity(x.klassfoo)
# output
# 3
# 0
# 0
Como puede ver, esto determinará la aridad mínima si una función toma una cantidad variable de argumentos. Tampoco tendrá en cuenta el argumento self o cls de un método de clase o instancia.
Sin embargo, para ser totalmente honesto, no usaría esta función en un entorno de producción a menos que supiera exactamente a qué funciones se llamaría, ya que hay mucho espacio para errores estúpidos. Esto puede derrotar el propósito.
Idealmente, querría parchear la función arity como un método en los funtores de Python. Así es cómo:
def arity(self, method):
return getattr(self.__class__, method).func_code.co_argcount - 1
functor = arity.__class__
functor.arity = arity
arity.__class__.arity = arity
Pero, CPython implementa los funtores en C, en realidad no se pueden modificar. Esto puede funcionar en PyPy, sin embargo.
Eso es todo asumiendo que su función arity () es correcta. ¿Qué pasa con las funciones variables? ¿Incluso quieres una respuesta entonces?
Utilice un decorador para decorar métodos por ejemplo
def arity(method):
def _arity():
return method.func_code.co_argcount - 1 # remove self
method.arity = _arity
return method
class Foo:
@arity
def bar(self, bla):
pass
print Foo().bar.arity()
Ahora implemente la función _arity
para calcular el conteo de arg en función de sus necesidades